1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[ORC] Add support for resource tracking/removal (removable code).

This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.

Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.

Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.

Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.

RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.

The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).

This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
This commit is contained in:
Lang Hames 2020-09-11 09:50:41 -07:00
parent 2d8b3a7239
commit efc9f3486a
29 changed files with 1884 additions and 741 deletions

View File

@ -72,6 +72,17 @@ public:
return Error::success();
}
Error notifyFailed(MaterializationResponsibility &MR) override {
return Error::success();
}
Error notifyRemovingResources(ResourceKey K) override {
return Error::success();
}
void notifyTransferringResources(ResourceKey DstKey,
ResourceKey SrcKey) override {}
private:
void printLinkGraph(jitlink::LinkGraph &G, StringRef Title) {
constexpr JITTargetAddress LineWidth = 16;

View File

@ -16,11 +16,13 @@
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
#include "llvm/ExecutionEngine/OrcV1Deprecation.h"
#include "llvm/Support/Debug.h"
#include <atomic>
#include <memory>
#include <vector>
@ -33,11 +35,66 @@ class ExecutionSession;
class MaterializationUnit;
class MaterializationResponsibility;
class JITDylib;
class ResourceTracker;
enum class SymbolState : uint8_t;
/// VModuleKey provides a unique identifier (allocated and managed by
/// ExecutionSessions) for a module added to the JIT.
using VModuleKey = uint64_t;
using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
using ResourceKey = uintptr_t;
/// API to remove / transfer ownership of JIT resources.
class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> {
private:
friend class ExecutionSession;
friend class JITDylib;
friend class MaterializationResponsibility;
public:
ResourceTracker(const ResourceTracker &) = delete;
ResourceTracker &operator=(const ResourceTracker &) = delete;
ResourceTracker(ResourceTracker &&) = delete;
ResourceTracker &operator=(ResourceTracker &) = delete;
~ResourceTracker();
/// Return the JITDylib targeted by this tracker.
JITDylib &getJITDylib() const {
return *reinterpret_cast<JITDylib *>(JDAndFlag.load() &
~static_cast<uintptr_t>(1));
}
/// Remove all resources associated with this key.
Error remove();
/// Transfer all resources associated with this key to the given
/// tracker, which must target the same JITDylib as this one.
void transferTo(ResourceTracker &DstRT);
/// Return true if this tracker has become defunct.
bool isDefunct() const { return JDAndFlag.load() & 0x1; }
/// Returns the key associated with this tracker.
/// This method should not be used except for debug logging: there is no
/// guarantee that the returned value will remain valid.
ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); }
private:
ResourceTracker(JITDylibSP JD);
void makeDefunct();
std::atomic_uintptr_t JDAndFlag;
};
/// Listens for ResourceTracker operations.
class ResourceManager {
public:
virtual ~ResourceManager();
virtual Error handleRemoveResources(ResourceKey K) = 0;
virtual void handleTransferResources(ResourceKey DstK, ResourceKey SrcK) = 0;
};
/// A set of symbol names (represented by SymbolStringPtrs for
// efficiency).
@ -318,6 +375,18 @@ using RegisterDependenciesFunction =
/// are no dependants to register with.
extern RegisterDependenciesFunction NoDependenciesToRegister;
class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> {
public:
static char ID;
ResourceTrackerDefunct(ResourceTrackerSP RT);
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
private:
ResourceTrackerSP RT;
};
/// Used to notify a JITDylib that the given set of symbols failed to
/// materialize.
class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
@ -408,7 +477,8 @@ private:
/// emit symbols, or abandon materialization by notifying any unmaterialized
/// symbols of an error.
class MaterializationResponsibility {
friend class MaterializationUnit;
friend class ExecutionSession;
public:
MaterializationResponsibility(MaterializationResponsibility &&) = delete;
MaterializationResponsibility &
@ -419,12 +489,15 @@ public:
/// emitted or notified of an error.
~MaterializationResponsibility();
/// Returns the ResourceTracker for this instance.
template <typename Func> Error withResourceKeyDo(Func &&F) const;
/// Returns the target JITDylib that these symbols are being materialized
/// into.
JITDylib &getTargetJITDylib() const { return *JD; }
/// Returns the VModuleKey for this instance.
VModuleKey getVModuleKey() const { return K; }
/// Returns the ExecutionSession for this instance.
ExecutionSession &getExecutionSession();
/// Returns the symbol flags map for this responsibility instance.
/// Note: The returned flags may have transient flags (Lazy, Materializing)
@ -509,13 +582,13 @@ public:
/// materializers to break up work based on run-time information (e.g.
/// by introspecting which symbols have actually been looked up and
/// materializing only those).
void replace(std::unique_ptr<MaterializationUnit> MU);
Error replace(std::unique_ptr<MaterializationUnit> MU);
/// Delegates responsibility for the given symbols to the returned
/// materialization responsibility. Useful for breaking up work between
/// threads, or different kinds of materialization processes.
std::unique_ptr<MaterializationResponsibility>
delegate(const SymbolNameSet &Symbols, VModuleKey NewKey = VModuleKey());
Expected<std::unique_ptr<MaterializationResponsibility>>
delegate(const SymbolNameSet &Symbols);
void addDependencies(const SymbolStringPtr &Name,
const SymbolDependenceMap &Dependencies);
@ -526,19 +599,17 @@ public:
private:
/// Create a MaterializationResponsibility for the given JITDylib and
/// initial symbols.
MaterializationResponsibility(std::shared_ptr<JITDylib> JD,
SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol, VModuleKey K)
MaterializationResponsibility(JITDylibSP JD, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol)
: JD(std::move(JD)), SymbolFlags(std::move(SymbolFlags)),
InitSymbol(std::move(InitSymbol)), K(std::move(K)) {
assert(this->JD && "Cannot initialize with null JD");
InitSymbol(std::move(InitSymbol)) {
assert(this->JD && "Cannot initialize with null JITDylib");
assert(!this->SymbolFlags.empty() && "Materializing nothing?");
}
std::shared_ptr<JITDylib> JD;
JITDylibSP JD;
SymbolFlagsMap SymbolFlags;
SymbolStringPtr InitSymbol;
VModuleKey K;
};
/// A MaterializationUnit represents a set of symbol definitions that can
@ -555,9 +626,9 @@ class MaterializationUnit {
public:
MaterializationUnit(SymbolFlagsMap InitalSymbolFlags,
SymbolStringPtr InitSymbol, VModuleKey K)
SymbolStringPtr InitSymbol)
: SymbolFlags(std::move(InitalSymbolFlags)),
InitSymbol(std::move(InitSymbol)), K(std::move(K)) {
InitSymbol(std::move(InitSymbol)) {
assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) &&
"If set, InitSymbol should appear in InitialSymbolFlags map");
}
@ -590,18 +661,10 @@ public:
protected:
SymbolFlagsMap SymbolFlags;
SymbolStringPtr InitSymbol;
VModuleKey K;
private:
virtual void anchor();
std::unique_ptr<MaterializationResponsibility>
createMaterializationResponsibility(std::shared_ptr<JITDylib> JD) {
return std::unique_ptr<MaterializationResponsibility>(
new MaterializationResponsibility(std::move(JD), std::move(SymbolFlags),
std::move(InitSymbol), K));
}
/// Implementations of this method should discard the given symbol
/// from the source (e.g. if the source is an LLVM IR Module and the
/// symbol is a function, delete the function body or mark it available
@ -609,16 +672,13 @@ private:
virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
};
using MaterializationUnitList =
std::vector<std::unique_ptr<MaterializationUnit>>;
/// A MaterializationUnit implementation for pre-existing absolute symbols.
///
/// All symbols will be resolved and marked ready as soon as the unit is
/// materialized.
class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
public:
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K);
AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
StringRef getName() const override;
@ -641,9 +701,9 @@ private:
/// \endcode
///
inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) {
absoluteSymbols(SymbolMap Symbols) {
return std::make_unique<AbsoluteSymbolsMaterializationUnit>(
std::move(Symbols), std::move(K));
std::move(Symbols));
}
/// A materialization unit for symbol aliases. Allows existing symbols to be
@ -660,7 +720,7 @@ public:
/// resolved.
ReExportsMaterializationUnit(JITDylib *SourceJD,
JITDylibLookupFlags SourceJDLookupFlags,
SymbolAliasMap Aliases, VModuleKey K);
SymbolAliasMap Aliases);
StringRef getName() const override;
@ -686,10 +746,9 @@ private:
/// return Err;
/// \endcode
inline std::unique_ptr<ReExportsMaterializationUnit>
symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) {
symbolAliases(SymbolAliasMap Aliases) {
return std::make_unique<ReExportsMaterializationUnit>(
nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases),
std::move(K));
nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases));
}
/// Create a materialization unit for re-exporting symbols from another JITDylib
@ -698,10 +757,9 @@ symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) {
inline std::unique_ptr<ReExportsMaterializationUnit>
reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
JITDylibLookupFlags SourceJDLookupFlags =
JITDylibLookupFlags::MatchExportedSymbolsOnly,
VModuleKey K = VModuleKey()) {
JITDylibLookupFlags::MatchExportedSymbolsOnly) {
return std::make_unique<ReExportsMaterializationUnit>(
&SourceJD, SourceJDLookupFlags, std::move(Aliases), std::move(K));
&SourceJD, SourceJDLookupFlags, std::move(Aliases));
}
/// Build a SymbolAliasMap for the common case where you want to re-export
@ -727,6 +785,7 @@ class AsynchronousSymbolQuery {
friend class ExecutionSession;
friend class JITDylib;
friend class JITSymbolResolverAdapter;
friend class MaterializationResponsibility;
public:
/// Create a query for the given symbols. The NotifyComplete
@ -776,7 +835,7 @@ private:
/// their addresses may be used as keys for resource management.
/// JITDylib state changes must be made via an ExecutionSession to guarantee
/// that they are synchronized with respect to other JITDylib operations.
class JITDylib : public std::enable_shared_from_this<JITDylib> {
class JITDylib : public ThreadSafeRefCountedBase<JITDylib> {
friend class AsynchronousSymbolQuery;
friend class ExecutionSession;
friend class Platform;
@ -813,6 +872,21 @@ public:
/// Get a reference to the ExecutionSession for this JITDylib.
ExecutionSession &getExecutionSession() const { return ES; }
/// Calls remove on all trackers currently associated with this JITDylib.
/// Does not run static deinits.
///
/// Note that removal happens outside the session lock, so new code may be
/// added concurrently while the clear is underway, and the newly added
/// code will *not* be cleared. Adding new code concurrently with a clear
/// is usually a bug and should be avoided.
Error clear();
/// Get the default resource tracker for this JITDylib.
ResourceTrackerSP getDefaultResourceTracker();
/// Create a resource tracker for this JITDylib.
ResourceTrackerSP createResourceTracker();
/// Adds a definition generator to this JITDylib and returns a referenece to
/// it.
///
@ -873,10 +947,13 @@ public:
/// Define all symbols provided by the materialization unit to be part of this
/// JITDylib.
///
/// If RT is not specified then the default resource tracker will be used.
///
/// This overload always takes ownership of the MaterializationUnit. If any
/// errors occur, the MaterializationUnit consumed.
template <typename MaterializationUnitType>
Error define(std::unique_ptr<MaterializationUnitType> &&MU);
Error define(std::unique_ptr<MaterializationUnitType> &&MU,
ResourceTrackerSP RT = nullptr);
/// Define all symbols provided by the materialization unit to be part of this
/// JITDylib.
@ -886,7 +963,8 @@ public:
/// may allow the caller to modify the MaterializationUnit to correct the
/// issue, then re-call define.
template <typename MaterializationUnitType>
Error define(std::unique_ptr<MaterializationUnitType> &MU);
Error define(std::unique_ptr<MaterializationUnitType> &MU,
ResourceTrackerSP RT = nullptr);
/// Tries to remove the given symbols.
///
@ -913,37 +991,41 @@ public:
/// Returns the given JITDylibs and all of their transitive dependencies in
/// DFS order (based on linkage relationships). Each JITDylib will appear
/// only once.
static std::vector<std::shared_ptr<JITDylib>>
getDFSLinkOrder(ArrayRef<std::shared_ptr<JITDylib>> JDs);
static std::vector<JITDylibSP> getDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
/// Returns the given JITDylibs and all of their transitive dependensies in
/// reverse DFS order (based on linkage relationships). Each JITDylib will
/// appear only once.
static std::vector<std::shared_ptr<JITDylib>>
getReverseDFSLinkOrder(ArrayRef<std::shared_ptr<JITDylib>> JDs);
static std::vector<JITDylibSP>
getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
/// Return this JITDylib and its transitive dependencies in DFS order
/// based on linkage relationships.
std::vector<std::shared_ptr<JITDylib>> getDFSLinkOrder();
std::vector<JITDylibSP> getDFSLinkOrder();
/// Rteurn this JITDylib and its transitive dependencies in reverse DFS order
/// based on linkage relationships.
std::vector<std::shared_ptr<JITDylib>> getReverseDFSLinkOrder();
std::vector<JITDylibSP> getReverseDFSLinkOrder();
private:
using AsynchronousSymbolQueryList =
std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
struct UnmaterializedInfo {
UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
: MU(std::move(MU)) {}
UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU,
ResourceTracker *RT)
: MU(std::move(MU)), RT(RT) {}
std::unique_ptr<MaterializationUnit> MU;
ResourceTracker *RT;
};
using UnmaterializedInfosMap =
DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
using UnmaterializedInfosList =
std::vector<std::shared_ptr<UnmaterializedInfo>>;
struct MaterializingInfo {
SymbolDependenceMap Dependants;
SymbolDependenceMap UnemittedDependencies;
@ -1010,18 +1092,27 @@ private:
JITDylib(ExecutionSession &ES, std::string Name);
ResourceTrackerSP getTracker(MaterializationResponsibility &MR);
std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
removeTracker(ResourceTracker &RT);
void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
Error defineImpl(MaterializationUnit &MU);
void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
ResourceTracker &RT);
void lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K,
JITDylibLookupFlags JDLookupFlags,
SymbolLookupSet &Unresolved);
Error lodgeQuery(MaterializationUnitList &MUs,
Error lodgeQuery(UnmaterializedInfosList &UMIs,
std::shared_ptr<AsynchronousSymbolQuery> &Q, LookupKind K,
JITDylibLookupFlags JDLookupFlags,
SymbolLookupSet &Unresolved);
Error lodgeQueryImpl(MaterializationUnitList &MUs,
Error lodgeQueryImpl(UnmaterializedInfosList &UMIs,
std::shared_ptr<AsynchronousSymbolQuery> &Q,
LookupKind K, JITDylibLookupFlags JDLookupFlags,
SymbolLookupSet &Unresolved);
@ -1035,20 +1126,30 @@ private:
Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
void replace(std::unique_ptr<MaterializationUnit> MU);
Error replace(MaterializationResponsibility &FromMR,
std::unique_ptr<MaterializationUnit> MU);
Expected<std::unique_ptr<MaterializationResponsibility>>
delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol);
SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
void addDependencies(const SymbolStringPtr &Name,
const SymbolDependenceMap &Dependants);
Error resolve(const SymbolMap &Resolved);
Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved);
Error emit(const SymbolFlagsMap &Emitted);
Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted);
void unlinkMaterializationResponsibility(MaterializationResponsibility &MR);
using FailedSymbolsWorklist =
std::vector<std::pair<JITDylib *, SymbolStringPtr>>;
static void notifyFailed(FailedSymbolsWorklist FailedSymbols);
static std::pair<AsynchronousSymbolQuerySet,
std::shared_ptr<SymbolDependenceMap>>
failSymbols(FailedSymbolsWorklist);
ExecutionSession &ES;
std::string JITDylibName;
@ -1058,6 +1159,11 @@ private:
MaterializingInfosMap MaterializingInfos;
std::vector<std::unique_ptr<DefinitionGenerator>> DefGenerators;
JITDylibSearchOrder LinkOrder;
ResourceTrackerSP DefaultTracker;
// Map trackers to sets of symbols tracked.
DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols;
DenseMap<MaterializationResponsibility *, ResourceTracker *> MRTrackers;
};
/// Platforms set up standard symbols and mediate interactions between dynamic
@ -1076,11 +1182,12 @@ public:
/// This method will be called under the ExecutionSession lock each time a
/// MaterializationUnit is added to a JITDylib.
virtual Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) = 0;
virtual Error notifyAdding(ResourceTracker &RT,
const MaterializationUnit &MU) = 0;
/// This method will be called under the ExecutionSession lock when a
/// VModuleKey is removed.
virtual Error notifyRemoving(JITDylib &JD, VModuleKey K) = 0;
/// ResourceTracker is removed.
virtual Error notifyRemoving(ResourceTracker &RT) = 0;
/// A utility function for looking up initializer symbols. Performs a blocking
/// lookup for the given symbols in each of the given JITDylibs.
@ -1093,6 +1200,7 @@ public:
class ExecutionSession {
// FIXME: Remove this when we remove the old ORC layers.
friend class JITDylib;
friend class ResourceTracker;
public:
/// For reporting errors.
@ -1108,6 +1216,9 @@ public:
/// SymbolStringPools may be shared between ExecutionSessions.
ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
/// End the session. Closes all JITDylibs.
Error endSession();
/// Add a symbol name to the SymbolStringPool and return a pointer to it.
SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
@ -1127,6 +1238,14 @@ public:
return F();
}
/// Register the given ResourceManager with this ExecutionSession.
/// Managers will be notified of events in reverse order of registration.
void registerResourceManager(ResourceManager &RM);
/// Deregister the given ResourceManager with this ExecutionSession.
/// Manager must have been previously registered.
void deregisterResourceManager(ResourceManager &RM);
/// Return a pointer to the "name" JITDylib.
/// Ownership of JITDylib remains within Execution Session
JITDylib *getJITDylibByName(StringRef Name);
@ -1152,17 +1271,6 @@ public:
/// If no Platform is attached this call is equivalent to createBareJITDylib.
Expected<JITDylib &> createJITDylib(std::string Name);
/// Allocate a module key for a new module to add to the JIT.
VModuleKey allocateVModule() {
return runSessionLocked([this]() { return ++LastKey; });
}
/// Return a module key to the ExecutionSession so that it can be
/// re-used. This should only be done once all resources associated
/// with the original key have been released.
void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
}
/// Set the error reporter function.
ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
this->ReportError = std::move(ReportError);
@ -1265,19 +1373,37 @@ private:
void runOutstandingMUs();
static std::unique_ptr<MaterializationResponsibility>
createMaterializationResponsibility(ResourceTracker &RT,
SymbolFlagsMap Symbols,
SymbolStringPtr InitSymbol) {
auto &JD = RT.getJITDylib();
std::unique_ptr<MaterializationResponsibility> MR(
new MaterializationResponsibility(&JD, std::move(Symbols),
std::move(InitSymbol)));
JD.MRTrackers[MR.get()] = &RT;
return MR;
}
Error removeResourceTracker(ResourceTracker &RT);
void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
void destroyResourceTracker(ResourceTracker &RT);
#ifndef NDEBUG
void dumpDispatchInfo(JITDylib &JD, MaterializationUnit &MU);
#endif // NDEBUG
mutable std::recursive_mutex SessionMutex;
bool SessionOpen = true;
std::shared_ptr<SymbolStringPool> SSP;
std::unique_ptr<Platform> P;
VModuleKey LastKey = 0;
ErrorReporter ReportError = logErrorsToStdErr;
DispatchMaterializationFunction DispatchMaterialization =
materializeOnCurrentThread;
std::vector<std::shared_ptr<JITDylib>> JDs;
std::vector<ResourceManager *> ResourceManagers;
std::vector<JITDylibSP> JDs;
// FIXME: Remove this (and runOutstandingMUs) once the linking layer works
// with callbacks from asynchronous queries.
@ -1287,6 +1413,22 @@ private:
OutstandingMUs;
};
inline ExecutionSession &MaterializationResponsibility::getExecutionSession() {
return JD->getExecutionSession();
}
template <typename Func>
Error MaterializationResponsibility::withResourceKeyDo(Func &&F) const {
return JD->getExecutionSession().runSessionLocked([&]() -> Error {
auto I = JD->MRTrackers.find(this);
assert(I != JD->MRTrackers.end() && "No tracker for this MR");
if (I->second->isDefunct())
return make_error<ResourceTrackerDefunct>(I->second);
F(I->second->getKeyUnsafe());
return Error::success();
});
}
template <typename GeneratorT>
GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
auto &G = *DefGenerator;
@ -1302,7 +1444,8 @@ auto JITDylib::withLinkOrderDo(Func &&F)
}
template <typename MaterializationUnitType>
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU,
ResourceTrackerSP RT) {
assert(MU && "Can not define with a null MU");
if (MU->getSymbols().empty()) {
@ -1321,22 +1464,22 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
if (auto Err = defineImpl(*MU))
return Err;
if (!RT)
RT = getDefaultResourceTracker();
if (auto *P = ES.getPlatform()) {
if (auto Err = P->notifyAdding(*this, *MU))
if (auto Err = P->notifyAdding(*RT, *MU))
return Err;
}
/// defineImpl succeeded.
auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
for (auto &KV : UMI->MU->getSymbols())
UnmaterializedInfos[KV.first] = UMI;
installMaterializationUnit(std::move(MU), *RT);
return Error::success();
});
}
template <typename MaterializationUnitType>
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU,
ResourceTrackerSP RT) {
assert(MU && "Can not define with a null MU");
if (MU->getSymbols().empty()) {
@ -1355,16 +1498,15 @@ Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
if (auto Err = defineImpl(*MU))
return Err;
if (!RT)
RT = getDefaultResourceTracker();
if (auto *P = ES.getPlatform()) {
if (auto Err = P->notifyAdding(*this, *MU))
if (auto Err = P->notifyAdding(*RT, *MU))
return Err;
}
/// defineImpl succeeded.
auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
for (auto &KV : UMI->MU->getSymbols())
UnmaterializedInfos[KV.first] = UMI;
installMaterializationUnit(std::move(MU), *RT);
return Error::success();
});
}

View File

@ -45,8 +45,8 @@ public:
IRSymbolMapper::ManglingOptions MO;
};
using NotifyCompiledFunction =
std::function<void(VModuleKey K, ThreadSafeModule TSM)>;
using NotifyCompiledFunction = std::function<void(
MaterializationResponsibility &R, ThreadSafeModule TSM)>;
IRCompileLayer(ExecutionSession &ES, ObjectLayer &BaseLayer,
std::unique_ptr<IRCompiler> Compile);

View File

@ -34,15 +34,15 @@ public:
/// SymbolFlags and SymbolToDefinition maps.
IRMaterializationUnit(ExecutionSession &ES,
const IRSymbolMapper::ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K);
ThreadSafeModule TSM);
/// Create an IRMaterializationLayer from a module, and pre-existing
/// SymbolFlags and SymbolToDefinition maps. The maps must provide
/// entries for each definition in M.
/// This constructor is useful for delegating work from one
/// IRMaterializationUnit to another.
IRMaterializationUnit(ThreadSafeModule TSM, VModuleKey K,
SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol,
IRMaterializationUnit(ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol,
SymbolNameToDefinitionMap SymbolToDefinition);
/// Return the ModuleIdentifier as the name for this MaterializationUnit.
@ -94,10 +94,15 @@ public:
/// Returns the current value of the CloneToNewContextOnEmit flag.
bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; }
/// Add a MaterializatinoUnit representing the given IR to the JITDylib
/// targeted by the given tracker.
virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM);
/// Adds a MaterializationUnit representing the given IR to the given
/// JITDylib.
virtual Error add(JITDylib &JD, ThreadSafeModule TSM,
VModuleKey K = VModuleKey());
/// JITDylib. If RT is not specif
Error add(JITDylib &JD, ThreadSafeModule TSM) {
return add(JD.getDefaultResourceTracker(), std::move(TSM));
}
/// Emit should materialize the given IR.
virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
@ -115,13 +120,12 @@ class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
public:
BasicIRLayerMaterializationUnit(IRLayer &L,
const IRSymbolMapper::ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K);
ThreadSafeModule TSM);
private:
void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
IRLayer &L;
VModuleKey K;
};
/// Interface for Layers that accept object files.
@ -135,8 +139,11 @@ public:
/// Adds a MaterializationUnit representing the given IR to the given
/// JITDylib.
virtual Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
VModuleKey K = VModuleKey());
virtual Error add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O);
Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
return add(JD.getDefaultResourceTracker(), std::move(O));
}
/// Emit should materialize the given IR.
virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
@ -151,9 +158,9 @@ private:
class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
public:
static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
Create(ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> O);
BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K,
BasicObjectLayerMaterializationUnit(ObjectLayer &L,
std::unique_ptr<MemoryBuffer> O,
SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol);

View File

@ -144,7 +144,7 @@ public:
IndirectStubsManager &ISManager,
JITDylib &SourceJD,
SymbolAliasMap CallableAliases,
ImplSymbolMap *SrcJDLoc, VModuleKey K);
ImplSymbolMap *SrcJDLoc);
StringRef getName() const override;
@ -166,11 +166,10 @@ private:
inline std::unique_ptr<LazyReexportsMaterializationUnit>
lazyReexports(LazyCallThroughManager &LCTManager,
IndirectStubsManager &ISManager, JITDylib &SourceJD,
SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc = nullptr,
VModuleKey K = VModuleKey()) {
SymbolAliasMap CallableAliases,
ImplSymbolMap *SrcJDLoc = nullptr) {
return std::make_unique<LazyReexportsMaterializationUnit>(
LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc,
std::move(K));
LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
}
} // End namespace orc

View File

@ -98,8 +98,9 @@ public:
ExecutionSession &getExecutionSession() const { return ES; }
Error setupJITDylib(JITDylib &JD) override;
Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override;
Error notifyRemoving(JITDylib &JD, VModuleKey K) override;
Error notifyAdding(ResourceTracker &RT,
const MaterializationUnit &MU) override;
Error notifyRemoving(ResourceTracker &RT) override;
Expected<InitializerSequence> getInitializerSequence(JITDylib &JD);
@ -119,6 +120,19 @@ private:
LocalDependenciesMap getSyntheticSymbolLocalDependencies(
MaterializationResponsibility &MR) override;
// FIXME: We should be tentatively tracking scraped sections and discarding
// if the MR fails.
Error notifyFailed(MaterializationResponsibility &MR) override {
return Error::success();
}
Error notifyRemovingResources(ResourceKey K) override {
return Error::success();
}
void notifyTransferringResources(ResourceKey DstKey,
ResourceKey SrcKey) override {}
private:
using InitSymbolDepMap =
DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;

View File

@ -51,7 +51,7 @@ class ObjectLinkingLayerJITLinkContext;
/// Clients can use this class to add relocatable object files to an
/// ExecutionSession, and it typically serves as the base layer (underneath
/// a compiling layer like IRCompileLayer) for the rest of the JIT.
class ObjectLinkingLayer : public ObjectLayer {
class ObjectLinkingLayer : public ObjectLayer, private ResourceManager {
friend class ObjectLinkingLayerJITLinkContext;
public:
@ -72,10 +72,10 @@ public:
virtual Error notifyEmitted(MaterializationResponsibility &MR) {
return Error::success();
}
virtual Error notifyRemovingModule(VModuleKey K) {
return Error::success();
}
virtual Error notifyRemovingAllModules() { return Error::success(); }
virtual Error notifyFailed(MaterializationResponsibility &MR) = 0;
virtual Error notifyRemovingResources(ResourceKey K) = 0;
virtual void notifyTransferringResources(ResourceKey DstKey,
ResourceKey SrcKey) = 0;
/// Return any dependencies that synthetic symbols (e.g. init symbols)
/// have on locally scoped jitlink::Symbols. This is used by the
@ -161,8 +161,8 @@ private:
void notifyLoaded(MaterializationResponsibility &MR);
Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
Error removeModule(VModuleKey K);
Error removeAllModules();
Error handleRemoveResources(ResourceKey K) override;
void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override;
mutable std::mutex LayerMutex;
jitlink::JITLinkMemoryManager &MemMgr;
@ -170,20 +170,22 @@ private:
bool OverrideObjectFlags = false;
bool AutoClaimObjectSymbols = false;
ReturnObjectBufferFunction ReturnObjectBuffer;
DenseMap<VModuleKey, AllocPtr> TrackedAllocs;
std::vector<AllocPtr> UntrackedAllocs;
DenseMap<ResourceKey, std::vector<AllocPtr>> Allocs;
std::vector<std::unique_ptr<Plugin>> Plugins;
};
class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
public:
EHFrameRegistrationPlugin(
ExecutionSession &ES,
std::unique_ptr<jitlink::EHFrameRegistrar> Registrar);
Error notifyEmitted(MaterializationResponsibility &MR) override;
void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
jitlink::PassConfiguration &PassConfig) override;
Error notifyRemovingModule(VModuleKey K) override;
Error notifyRemovingAllModules() override;
Error notifyEmitted(MaterializationResponsibility &MR) override;
Error notifyFailed(MaterializationResponsibility &MR) override;
Error notifyRemovingResources(ResourceKey K) override;
void notifyTransferringResources(ResourceKey DstKey,
ResourceKey SrcKey) override;
private:
@ -193,10 +195,10 @@ private:
};
std::mutex EHFramePluginMutex;
ExecutionSession &ES;
std::unique_ptr<jitlink::EHFrameRegistrar> Registrar;
DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks;
DenseMap<VModuleKey, EHFrameRange> TrackedEHFrameRanges;
std::vector<EHFrameRange> UntrackedEHFrameRanges;
DenseMap<ResourceKey, std::vector<EHFrameRange>> EHFrameRanges;
};
} // end namespace orc

View File

@ -35,16 +35,16 @@
namespace llvm {
namespace orc {
class RTDyldObjectLinkingLayer : public ObjectLayer {
class RTDyldObjectLinkingLayer : public ObjectLayer, private ResourceManager {
public:
/// Functor for receiving object-loaded notifications.
using NotifyLoadedFunction =
std::function<void(VModuleKey, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &)>;
using NotifyLoadedFunction = std::function<void(
MaterializationResponsibility &R, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &)>;
/// Functor for receiving finalization notifications.
using NotifyEmittedFunction =
std::function<void(VModuleKey, std::unique_ptr<MemoryBuffer>)>;
using NotifyEmittedFunction = std::function<void(
MaterializationResponsibility &R, std::unique_ptr<MemoryBuffer>)>;
using GetMemoryManagerFunction =
std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>;
@ -122,16 +122,23 @@ public:
void unregisterJITEventListener(JITEventListener &L);
private:
Error onObjLoad(VModuleKey K, MaterializationResponsibility &R,
using MemoryManagerUP = std::unique_ptr<RuntimeDyld::MemoryManager>;
Error onObjLoad(MaterializationResponsibility &R,
const object::ObjectFile &Obj,
RuntimeDyld::MemoryManager *MemMgr,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
RuntimeDyld::MemoryManager &MemMgr,
RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> Resolved,
std::set<StringRef> &InternalSymbols);
void onObjEmit(VModuleKey K, MaterializationResponsibility &R,
void onObjEmit(MaterializationResponsibility &R,
object::OwningBinary<object::ObjectFile> O,
RuntimeDyld::MemoryManager *MemMgr, Error Err);
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
Error Err);
Error handleRemoveResources(ResourceKey K) override;
void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override;
mutable std::mutex RTDyldLayerMutex;
GetMemoryManagerFunction GetMemoryManager;
@ -140,11 +147,8 @@ private:
bool ProcessAllSections = false;
bool OverrideObjectFlags = false;
bool AutoClaimObjectSymbols = false;
std::vector<std::unique_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
DenseMap<ResourceKey, std::vector<MemoryManagerUP>> MemMgrs;
std::vector<JITEventListener *> EventListeners;
DenseMap<RuntimeDyld::MemoryManager *,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
LoadedObjInfos;
};
} // end namespace orc

View File

@ -271,11 +271,11 @@ private:
object::OwningBinary<object::ObjectFile> O,
RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver,
bool ProcessAllSections,
unique_function<Error(const object::ObjectFile &Obj,
std::unique_ptr<LoadedObjectInfo>,
unique_function<Error(const object::ObjectFile &Obj, LoadedObjectInfo &,
std::map<StringRef, JITEvaluatedSymbol>)>
OnLoaded,
unique_function<void(object::OwningBinary<object::ObjectFile> O, Error)>
unique_function<void(object::OwningBinary<object::ObjectFile> O,
std::unique_ptr<LoadedObjectInfo>, Error)>
OnEmitted);
// RuntimeDyldImpl is the actual class. RuntimeDyld is just the public
@ -298,10 +298,11 @@ void jitLinkForORC(
RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver,
bool ProcessAllSections,
unique_function<Error(const object::ObjectFile &Obj,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>,
RuntimeDyld::LoadedObjectInfo &,
std::map<StringRef, JITEvaluatedSymbol>)>
OnLoaded,
unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
unique_function<void(object::OwningBinary<object::ObjectFile>,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)>
OnEmitted);
} // end namespace llvm

View File

@ -73,17 +73,16 @@ class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
public:
PartitioningIRMaterializationUnit(ExecutionSession &ES,
const IRSymbolMapper::ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K,
ThreadSafeModule TSM,
CompileOnDemandLayer &Parent)
: IRMaterializationUnit(ES, MO, std::move(TSM), std::move(K)),
Parent(Parent) {}
: IRMaterializationUnit(ES, MO, std::move(TSM)), Parent(Parent) {}
PartitioningIRMaterializationUnit(
ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,
ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition,
CompileOnDemandLayer &Parent)
: IRMaterializationUnit(std::move(TSM), std::move(K),
std::move(SymbolFlags), std::move(InitSymbol),
: IRMaterializationUnit(std::move(TSM), std::move(SymbolFlags),
std::move(InitSymbol),
std::move(SymbolToDefinition)),
Parent(Parent) {}
@ -158,19 +157,29 @@ void CompileOnDemandLayer::emit(
// implementation dylib.
if (auto Err = PDR.getImplDylib().define(
std::make_unique<PartitioningIRMaterializationUnit>(
ES, *getManglingOptions(), std::move(TSM), R->getVModuleKey(),
*this))) {
ES, *getManglingOptions(), std::move(TSM), *this))) {
ES.reportError(std::move(Err));
R->failMaterialization();
return;
}
if (!NonCallables.empty())
R->replace(reexports(PDR.getImplDylib(), std::move(NonCallables),
JITDylibLookupFlags::MatchAllSymbols));
if (!Callables.empty())
R->replace(lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
std::move(Callables), AliaseeImpls));
if (auto Err =
R->replace(reexports(PDR.getImplDylib(), std::move(NonCallables),
JITDylibLookupFlags::MatchAllSymbols))) {
getExecutionSession().reportError(std::move(Err));
R->failMaterialization();
return;
}
if (!Callables.empty()) {
if (auto Err = R->replace(
lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
std::move(Callables), AliaseeImpls))) {
getExecutionSession().reportError(std::move(Err));
R->failMaterialization();
return;
}
}
}
CompileOnDemandLayer::PerDylibResources &
@ -285,9 +294,14 @@ void CompileOnDemandLayer::emitPartition(
// If the partition is empty, return the whole module to the symbol table.
if (GVsToExtract->empty()) {
R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
std::move(TSM), R->getVModuleKey(), R->getSymbols(),
R->getInitializerSymbol(), std::move(Defs), *this));
if (auto Err =
R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
std::move(TSM), R->getSymbols(), R->getInitializerSymbol(),
std::move(Defs), *this))) {
getExecutionSession().reportError(std::move(Err));
R->failMaterialization();
return;
}
return;
}
@ -352,8 +366,12 @@ void CompileOnDemandLayer::emitPartition(
return;
}
R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
ES, *getManglingOptions(), std::move(TSM), R->getVModuleKey(), *this));
if (auto Err = R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
ES, *getManglingOptions(), std::move(TSM), *this))) {
ES.reportError(std::move(Err));
R->failMaterialization();
return;
}
BaseLayer.emit(std::move(R), std::move(*ExtractedTSM));
}

File diff suppressed because it is too large Load Diff

View File

@ -397,8 +397,7 @@ Error StaticLibraryDefinitionGenerator::tryToGenerate(
MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
ChildBufferInfo.second);
if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false),
VModuleKey()))
if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false)))
return Err;
}

View File

@ -33,7 +33,7 @@ void IRCompileLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
{
std::lock_guard<std::mutex> Lock(IRLayerMutex);
if (NotifyCompiled)
NotifyCompiled(R->getVModuleKey(), std::move(TSM));
NotifyCompiled(*R, std::move(TSM));
else
TSM = ThreadSafeModule();
}

View File

@ -25,9 +25,9 @@ public:
using CompileFunction = JITCompileCallbackManager::CompileFunction;
CompileCallbackMaterializationUnit(SymbolStringPtr Name,
CompileFunction Compile, VModuleKey K)
CompileFunction Compile)
: MaterializationUnit(SymbolFlagsMap({{Name, JITSymbolFlags::Exported}}),
nullptr, std::move(K)),
nullptr),
Name(std::move(Name)), Compile(std::move(Compile)) {}
StringRef getName() const override { return "<Compile Callbacks>"; }
@ -65,10 +65,9 @@ JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
std::lock_guard<std::mutex> Lock(CCMgrMutex);
AddrToSymbol[*TrampolineAddr] = CallbackName;
cantFail(CallbacksJD.define(
std::make_unique<CompileCallbackMaterializationUnit>(
std::move(CallbackName), std::move(Compile),
ES.allocateVModule())));
cantFail(
CallbacksJD.define(std::make_unique<CompileCallbackMaterializationUnit>(
std::move(CallbackName), std::move(Compile))));
return *TrampolineAddr;
} else
return TrampolineAddr.takeError();

View File

@ -88,8 +88,9 @@ class GenericLLVMIRPlatform : public Platform {
public:
GenericLLVMIRPlatform(GenericLLVMIRPlatformSupport &S) : S(S) {}
Error setupJITDylib(JITDylib &JD) override;
Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override;
Error notifyRemoving(JITDylib &JD, VModuleKey K) override {
Error notifyAdding(ResourceTracker &RT,
const MaterializationUnit &MU) override;
Error notifyRemoving(ResourceTracker &RT) override {
// Noop -- Nothing to do (yet).
return Error::success();
}
@ -187,7 +188,8 @@ public:
return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx)));
}
Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) {
auto &JD = RT.getJITDylib();
if (auto &InitSym = MU.getInitializerSymbol())
InitSymbols[&JD].add(InitSym, SymbolLookupFlags::WeaklyReferencedSymbol);
else {
@ -261,7 +263,7 @@ private:
return std::move(Err);
DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;
std::vector<std::shared_ptr<JITDylib>> DFSLinkOrder;
std::vector<JITDylibSP> DFSLinkOrder;
getExecutionSession().runSessionLocked([&]() {
DFSLinkOrder = JD.getDFSLinkOrder();
@ -311,7 +313,7 @@ private:
auto LLJITRunAtExits = J.mangleAndIntern("__lljit_run_atexits");
DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;
std::vector<std::shared_ptr<JITDylib>> DFSLinkOrder;
std::vector<JITDylibSP> DFSLinkOrder;
ES.runSessionLocked([&]() {
DFSLinkOrder = JD.getDFSLinkOrder();
@ -365,7 +367,7 @@ private:
/// JITDylibs that it depends on).
Error issueInitLookups(JITDylib &JD) {
DenseMap<JITDylib *, SymbolLookupSet> RequiredInitSymbols;
std::vector<std::shared_ptr<JITDylib>> DFSLinkOrder;
std::vector<JITDylibSP> DFSLinkOrder;
getExecutionSession().runSessionLocked([&]() {
DFSLinkOrder = JD.getDFSLinkOrder();
@ -446,9 +448,9 @@ Error GenericLLVMIRPlatform::setupJITDylib(JITDylib &JD) {
return S.setupJITDylib(JD);
}
Error GenericLLVMIRPlatform::notifyAdding(JITDylib &JD,
Error GenericLLVMIRPlatform::notifyAdding(ResourceTracker &RT,
const MaterializationUnit &MU) {
return S.notifyAdding(JD, MU);
return S.notifyAdding(RT, MU);
}
Expected<ThreadSafeModule>
@ -961,7 +963,7 @@ Error LLJITBuilderState::prepareForConstruction() {
ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(
ES, std::make_unique<jitlink::InProcessMemoryManager>());
ObjLinkingLayer->addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
std::make_unique<jitlink::InProcessEHFrameRegistrar>()));
ES, std::make_unique<jitlink::InProcessEHFrameRegistrar>()));
return std::move(ObjLinkingLayer);
};
}
@ -973,6 +975,8 @@ Error LLJITBuilderState::prepareForConstruction() {
LLJIT::~LLJIT() {
if (CompileThreads)
CompileThreads->wait();
if (auto Err = ES->endSession())
ES->reportError(std::move(Err));
}
Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
@ -982,14 +986,13 @@ Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
TSM.withModuleDo([&](Module &M) { return applyDataLayout(M); }))
return Err;
return InitHelperTransformLayer->add(JD, std::move(TSM),
ES->allocateVModule());
return InitHelperTransformLayer->add(JD, std::move(TSM));
}
Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
assert(Obj && "Can not add null object");
return ObjTransformLayer.add(JD, std::move(Obj), ES->allocateVModule());
return ObjTransformLayer.add(JD, std::move(Obj));
}
Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
@ -1157,7 +1160,7 @@ Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
[&](Module &M) -> Error { return applyDataLayout(M); }))
return Err;
return CODLayer->add(JD, std::move(TSM), ES->allocateVModule());
return CODLayer->add(JD, std::move(TSM));
}
LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {

View File

@ -22,16 +22,18 @@ namespace orc {
IRLayer::~IRLayer() {}
Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) {
Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
assert(RT && "RT can not be null");
auto &JD = RT->getJITDylib();
return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
*this, *getManglingOptions(), std::move(TSM), std::move(K)));
*this, *getManglingOptions(), std::move(TSM)),
std::move(RT));
}
IRMaterializationUnit::IRMaterializationUnit(
ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
ThreadSafeModule TSM, VModuleKey K)
: MaterializationUnit(SymbolFlagsMap(), nullptr, std::move(K)),
TSM(std::move(TSM)) {
ThreadSafeModule TSM)
: MaterializationUnit(SymbolFlagsMap(), nullptr), TSM(std::move(TSM)) {
assert(this->TSM && "Module must not be null");
@ -96,10 +98,9 @@ IRMaterializationUnit::IRMaterializationUnit(
}
IRMaterializationUnit::IRMaterializationUnit(
ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,
ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition)
: MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),
std::move(K)),
: MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol)),
TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {}
StringRef IRMaterializationUnit::getName() const {
@ -126,11 +127,9 @@ void IRMaterializationUnit::discard(const JITDylib &JD,
}
BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM,
VModuleKey K)
: IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM),
std::move(K)),
L(L), K(std::move(K)) {}
IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
: IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
}
void BasicIRLayerMaterializationUnit::materialize(
std::unique_ptr<MaterializationResponsibility> R) {
@ -160,17 +159,17 @@ ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
ObjectLayer::~ObjectLayer() {}
Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
VModuleKey K) {
auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K),
std::move(O));
Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
assert(RT && "RT can not be null");
auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(O));
if (!ObjMU)
return ObjMU.takeError();
return JD.define(std::move(*ObjMU));
auto &JD = RT->getJITDylib();
return JD.define(std::move(*ObjMU), std::move(RT));
}
Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,
BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
std::unique_ptr<MemoryBuffer> O) {
auto ObjSymInfo =
getObjectSymbolInfo(L.getExecutionSession(), O->getMemBufferRef());
@ -183,15 +182,14 @@ BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,
return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
new BasicObjectLayerMaterializationUnit(
L, K, std::move(O), std::move(SymbolFlags), std::move(InitSymbol)));
L, std::move(O), std::move(SymbolFlags), std::move(InitSymbol)));
}
BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O,
SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol)
: MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),
std::move(K)),
L(L), O(std::move(O)) {}
ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol)
: MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol)), L(L),
O(std::move(O)) {}
StringRef BasicObjectLayerMaterializationUnit::getName() const {
if (O)

View File

@ -143,9 +143,8 @@ createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc,
VModuleKey K)
: MaterializationUnit(extractFlags(CallableAliases), nullptr, std::move(K)),
JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
: MaterializationUnit(extractFlags(CallableAliases), nullptr),
LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
@ -166,8 +165,13 @@ void LazyReexportsMaterializationUnit::materialize(
}
if (!CallableAliases.empty())
R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
std::move(CallableAliases), AliaseeTable));
if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
std::move(CallableAliases),
AliaseeTable))) {
R->getExecutionSession().reportError(std::move(Err));
R->failMaterialization();
return;
}
IndirectStubsManager::StubInitsMap StubInits;
for (auto &Alias : RequestedAliases) {

View File

@ -159,7 +159,9 @@ Error MachOPlatform::setupJITDylib(JITDylib &JD) {
return ObjLinkingLayer.add(JD, std::move(ObjBuffer));
}
Error MachOPlatform::notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
Error MachOPlatform::notifyAdding(ResourceTracker &RT,
const MaterializationUnit &MU) {
auto &JD = RT.getJITDylib();
const auto &InitSym = MU.getInitializerSymbol();
if (!InitSym)
return Error::success();
@ -173,7 +175,7 @@ Error MachOPlatform::notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
return Error::success();
}
Error MachOPlatform::notifyRemoving(JITDylib &JD, VModuleKey K) {
Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {
llvm_unreachable("Not supported yet");
}
@ -185,7 +187,7 @@ MachOPlatform::getInitializerSequence(JITDylib &JD) {
<< JD.getName() << "\n";
});
std::vector<std::shared_ptr<JITDylib>> DFSLinkOrder;
std::vector<JITDylibSP> DFSLinkOrder;
while (true) {
@ -247,7 +249,7 @@ MachOPlatform::getInitializerSequence(JITDylib &JD) {
Expected<MachOPlatform::DeinitializerSequence>
MachOPlatform::getDeinitializerSequence(JITDylib &JD) {
std::vector<std::shared_ptr<JITDylib>> DFSLinkOrder = JD.getDFSLinkOrder();
std::vector<JITDylibSP> DFSLinkOrder = JD.getDFSLinkOrder();
DeinitializerSequence FullDeinitSeq;
{

View File

@ -44,6 +44,8 @@ public:
}
void notifyFailed(Error Err) override {
for (auto &P : Layer.Plugins)
Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
Layer.getExecutionSession().reportError(std::move(Err));
MR->failMaterialization();
}
@ -442,15 +444,19 @@ ObjectLinkingLayer::Plugin::~Plugin() {}
ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
JITLinkMemoryManager &MemMgr)
: ObjectLayer(ES), MemMgr(MemMgr) {}
: ObjectLayer(ES), MemMgr(MemMgr) {
ES.registerResourceManager(*this);
}
ObjectLinkingLayer::ObjectLinkingLayer(
ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
: ObjectLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {}
: ObjectLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
ES.registerResourceManager(*this);
}
ObjectLinkingLayer::~ObjectLinkingLayer() {
if (auto Err = removeAllModules())
getExecutionSession().reportError(std::move(Err));
assert(Allocs.empty() && "Layer destroyed with resources still attached");
getExecutionSession().deregisterResourceManager(*this);
}
void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
@ -481,63 +487,56 @@ Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
if (Err)
return Err;
{
std::lock_guard<std::mutex> Lock(LayerMutex);
UntrackedAllocs.push_back(std::move(Alloc));
}
return Error::success();
return MR.withResourceKeyDo(
[&](ResourceKey K) { Allocs[K].push_back(std::move(Alloc)); });
}
Error ObjectLinkingLayer::removeModule(VModuleKey K) {
Error Err = Error::success();
for (auto &P : Plugins)
Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
AllocPtr Alloc;
{
std::lock_guard<std::mutex> Lock(LayerMutex);
auto AllocItr = TrackedAllocs.find(K);
Alloc = std::move(AllocItr->second);
TrackedAllocs.erase(AllocItr);
}
assert(Alloc && "No allocation for key K");
return joinErrors(std::move(Err), Alloc->deallocate());
}
Error ObjectLinkingLayer::removeAllModules() {
Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
Error Err = Error::success();
for (auto &P : Plugins)
Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
Err = joinErrors(std::move(Err), P->notifyRemovingResources(K));
std::vector<AllocPtr> Allocs;
{
std::lock_guard<std::mutex> Lock(LayerMutex);
Allocs = std::move(UntrackedAllocs);
std::vector<AllocPtr> AllocsToRemove;
getExecutionSession().runSessionLocked([&] {
auto I = Allocs.find(K);
if (I != Allocs.end()) {
std::swap(AllocsToRemove, I->second);
Allocs.erase(I);
}
});
for (auto &KV : TrackedAllocs)
Allocs.push_back(std::move(KV.second));
TrackedAllocs.clear();
}
while (!Allocs.empty()) {
Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
Allocs.pop_back();
while (!AllocsToRemove.empty()) {
Err = joinErrors(std::move(Err), AllocsToRemove.back()->deallocate());
AllocsToRemove.pop_back();
}
return Err;
}
void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
ResourceKey SrcKey) {
auto I = Allocs.find(SrcKey);
if (I != Allocs.end()) {
auto &SrcAllocs = I->second;
auto &DstAllocs = Allocs[DstKey];
DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
for (auto &Alloc : SrcAllocs)
DstAllocs.push_back(std::move(Alloc));
// Erase SrcKey entry using value rather than iterator I: I may have been
// invalidated when we looked up DstKey.
Allocs.erase(SrcKey);
}
for (auto &P : Plugins)
P->notifyTransferringResources(DstKey, SrcKey);
}
EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
std::unique_ptr<EHFrameRegistrar> Registrar)
: Registrar(std::move(Registrar)) {}
ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
: ES(ES), Registrar(std::move(Registrar)) {}
void EHFrameRegistrationPlugin::modifyPassConfig(
MaterializationResponsibility &MR, const Triple &TT,
@ -556,64 +555,70 @@ void EHFrameRegistrationPlugin::modifyPassConfig(
Error EHFrameRegistrationPlugin::notifyEmitted(
MaterializationResponsibility &MR) {
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
auto EHFrameRangeItr = InProcessLinks.find(&MR);
if (EHFrameRangeItr == InProcessLinks.end())
return Error::success();
EHFrameRange EmittedRange;
{
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
auto EHFrameRange = EHFrameRangeItr->second;
assert(EHFrameRange.Addr &&
"eh-frame addr to register can not be null");
auto EHFrameRangeItr = InProcessLinks.find(&MR);
if (EHFrameRangeItr == InProcessLinks.end())
return Error::success();
InProcessLinks.erase(EHFrameRangeItr);
if (auto Key = MR.getVModuleKey())
TrackedEHFrameRanges[Key] = EHFrameRange;
else
UntrackedEHFrameRanges.push_back(EHFrameRange);
EmittedRange = EHFrameRangeItr->second;
assert(EmittedRange.Addr && "eh-frame addr to register can not be null");
InProcessLinks.erase(EHFrameRangeItr);
}
return Registrar->registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
if (auto Err = MR.withResourceKeyDo(
[&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
return Err;
return Registrar->registerEHFrames(EmittedRange.Addr, EmittedRange.Size);
}
Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
Error EHFrameRegistrationPlugin::notifyFailed(
MaterializationResponsibility &MR) {
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
if (EHFrameRangeItr == TrackedEHFrameRanges.end())
return Error::success();
auto EHFrameRange = EHFrameRangeItr->second;
assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
TrackedEHFrameRanges.erase(EHFrameRangeItr);
return Registrar->deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
InProcessLinks.erase(&MR);
return Error::success();
}
Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
std::vector<EHFrameRange> RangesToRemove;
std::vector<EHFrameRange> EHFrameRanges =
std::move(UntrackedEHFrameRanges);
EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
for (auto &KV : TrackedEHFrameRanges)
EHFrameRanges.push_back(KV.second);
TrackedEHFrameRanges.clear();
ES.runSessionLocked([&] {
auto I = EHFrameRanges.find(K);
if (I != EHFrameRanges.end()) {
RangesToRemove = std::move(I->second);
EHFrameRanges.erase(I);
}
});
Error Err = Error::success();
while (!EHFrameRanges.empty()) {
auto EHFrameRange = EHFrameRanges.back();
assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
EHFrameRanges.pop_back();
Err = joinErrors(std::move(Err), Registrar->deregisterEHFrames(
EHFrameRange.Addr, EHFrameRange.Size));
while (!RangesToRemove.empty()) {
auto RangeToRemove = RangesToRemove.back();
RangesToRemove.pop_back();
assert(RangeToRemove.Addr && "Untracked eh-frame range must not be null");
Err = joinErrors(
std::move(Err),
Registrar->deregisterEHFrames(RangeToRemove.Addr, RangeToRemove.Size));
}
return Err;
}
void EHFrameRegistrationPlugin::notifyTransferringResources(
ResourceKey DstKey, ResourceKey SrcKey) {
auto SI = EHFrameRanges.find(SrcKey);
if (SI != EHFrameRanges.end()) {
auto &SrcRanges = SI->second;
auto &DstRanges = EHFrameRanges[DstKey];
DstRanges.reserve(DstRanges.size() + SrcRanges.size());
for (auto &SrcRange : SrcRanges)
DstRanges.push_back(std::move(SrcRange));
EHFrameRanges.erase(SI);
}
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -77,16 +77,12 @@ namespace orc {
RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
: ObjectLayer(ES), GetMemoryManager(GetMemoryManager) {}
: ObjectLayer(ES), GetMemoryManager(GetMemoryManager) {
ES.registerResourceManager(*this);
}
RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() {
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
for (auto &MemMgr : MemMgrs) {
for (auto *L : EventListeners)
L->notifyFreeingObject(
static_cast<uint64_t>(reinterpret_cast<uintptr_t>(MemMgr.get())));
MemMgr->deregisterEHFrames();
}
assert(MemMgrs.empty() && "Layer destroyed with resources still attached");
}
void RTDyldObjectLinkingLayer::emit(
@ -141,16 +137,8 @@ void RTDyldObjectLinkingLayer::emit(
}
}
auto K = R->getVModuleKey();
RuntimeDyld::MemoryManager *MemMgr = nullptr;
// Create a record a memory manager for this object.
{
auto Tmp = GetMemoryManager();
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
MemMgrs.push_back(std::move(Tmp));
MemMgr = MemMgrs.back().get();
}
auto MemMgr = GetMemoryManager();
auto &MemMgrRef = *MemMgr;
// Switch to shared ownership of MR so that it can be captured by both
// lambdas below.
@ -160,17 +148,20 @@ void RTDyldObjectLinkingLayer::emit(
jitLinkForORC(
object::OwningBinary<object::ObjectFile>(std::move(*Obj), std::move(O)),
*MemMgr, Resolver, ProcessAllSections,
[this, K, SharedR, MemMgr, InternalSymbols](
MemMgrRef, Resolver, ProcessAllSections,
[this, SharedR, &MemMgrRef, InternalSymbols](
const object::ObjectFile &Obj,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
return onObjLoad(K, *SharedR, Obj, MemMgr, std::move(LoadedObjInfo),
return onObjLoad(*SharedR, Obj, MemMgrRef, LoadedObjInfo,
ResolvedSymbols, *InternalSymbols);
},
[this, K, SharedR, MemMgr](object::OwningBinary<object::ObjectFile> Obj,
Error Err) mutable {
onObjEmit(K, *SharedR, std::move(Obj), MemMgr, std::move(Err));
[this, SharedR, MemMgr = std::move(MemMgr)](
object::OwningBinary<object::ObjectFile> Obj,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
Error Err) mutable {
onObjEmit(*SharedR, std::move(Obj), std::move(MemMgr),
std::move(LoadedObjInfo), std::move(Err));
});
}
@ -190,9 +181,9 @@ void RTDyldObjectLinkingLayer::unregisterJITEventListener(JITEventListener &L) {
}
Error RTDyldObjectLinkingLayer::onObjLoad(
VModuleKey K, MaterializationResponsibility &R,
const object::ObjectFile &Obj, RuntimeDyld::MemoryManager *MemMgr,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
MaterializationResponsibility &R, const object::ObjectFile &Obj,
RuntimeDyld::MemoryManager &MemMgr,
RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> Resolved,
std::set<StringRef> &InternalSymbols) {
SymbolFlagsMap ExtraSymbolsToClaim;
@ -273,19 +264,16 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
}
if (NotifyLoaded)
NotifyLoaded(K, Obj, *LoadedObjInfo);
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
assert(!LoadedObjInfos.count(MemMgr) && "Duplicate loaded info for MemMgr");
LoadedObjInfos[MemMgr] = std::move(LoadedObjInfo);
NotifyLoaded(R, Obj, LoadedObjInfo);
return Error::success();
}
void RTDyldObjectLinkingLayer::onObjEmit(
VModuleKey K, MaterializationResponsibility &R,
MaterializationResponsibility &R,
object::OwningBinary<object::ObjectFile> O,
RuntimeDyld::MemoryManager *MemMgr, Error Err) {
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, Error Err) {
if (Err) {
getExecutionSession().reportError(std::move(Err));
R.failMaterialization();
@ -305,17 +293,59 @@ void RTDyldObjectLinkingLayer::onObjEmit(
// Run EventListener notifyLoaded callbacks.
{
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
auto LOIItr = LoadedObjInfos.find(MemMgr);
assert(LOIItr != LoadedObjInfos.end() && "LoadedObjInfo missing");
for (auto *L : EventListeners)
L->notifyObjectLoaded(
static_cast<uint64_t>(reinterpret_cast<uintptr_t>(MemMgr)), *Obj,
*LOIItr->second);
LoadedObjInfos.erase(MemMgr);
L->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr.get()), *Obj,
*LoadedObjInfo);
}
if (NotifyEmitted)
NotifyEmitted(K, std::move(ObjBuffer));
NotifyEmitted(R, std::move(ObjBuffer));
if (auto Err = R.withResourceKeyDo(
[&](ResourceKey K) { MemMgrs[K].push_back(std::move(MemMgr)); })) {
getExecutionSession().reportError(std::move(Err));
R.failMaterialization();
}
}
Error RTDyldObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
std::vector<MemoryManagerUP> MemMgrsToRemove;
getExecutionSession().runSessionLocked([&] {
auto I = MemMgrs.find(K);
if (I != MemMgrs.end()) {
std::swap(MemMgrsToRemove, I->second);
MemMgrs.erase(I);
}
});
{
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
for (auto &MemMgr : MemMgrsToRemove) {
for (auto *L : EventListeners)
L->notifyFreeingObject(pointerToJITTargetAddress(MemMgr.get()));
MemMgr->deregisterEHFrames();
}
}
return Error::success();
}
void RTDyldObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
ResourceKey SrcKey) {
auto I = MemMgrs.find(SrcKey);
if (I != MemMgrs.end()) {
auto &SrcMemMgrs = I->second;
auto &DstMemMgrs = MemMgrs[DstKey];
DstMemMgrs.reserve(DstMemMgrs.size() + SrcMemMgrs.size());
for (auto &MemMgr : SrcMemMgrs)
DstMemMgrs.push_back(std::move(MemMgr));
// Erase SrcKey entry using value rather than iterator I: I may have been
// invalidated when we looked up DstKey.
MemMgrs.erase(SrcKey);
}
}
} // End namespace orc.

View File

@ -1200,16 +1200,19 @@ Error RuntimeDyldImpl::resolveExternalSymbols() {
void RuntimeDyldImpl::finalizeAsync(
std::unique_ptr<RuntimeDyldImpl> This,
unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
unique_function<void(object::OwningBinary<object::ObjectFile>,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)>
OnEmitted,
object::OwningBinary<object::ObjectFile> O) {
object::OwningBinary<object::ObjectFile> O,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info) {
auto SharedThis = std::shared_ptr<RuntimeDyldImpl>(std::move(This));
auto PostResolveContinuation =
[SharedThis, OnEmitted = std::move(OnEmitted), O = std::move(O)](
[SharedThis, OnEmitted = std::move(OnEmitted), O = std::move(O),
Info = std::move(Info)](
Expected<JITSymbolResolver::LookupResult> Result) mutable {
if (!Result) {
OnEmitted(std::move(O), Result.takeError());
OnEmitted(std::move(O), std::move(Info), Result.takeError());
return;
}
@ -1223,11 +1226,11 @@ void RuntimeDyldImpl::finalizeAsync(
SharedThis->registerEHFrames();
std::string ErrMsg;
if (SharedThis->MemMgr.finalizeMemory(&ErrMsg))
OnEmitted(std::move(O),
OnEmitted(std::move(O), std::move(Info),
make_error<StringError>(std::move(ErrMsg),
inconvertibleErrorCode()));
else
OnEmitted(std::move(O), Error::success());
OnEmitted(std::move(O), std::move(Info), Error::success());
};
JITSymbolResolver::LookupSet Symbols;
@ -1418,12 +1421,12 @@ void jitLinkForORC(
object::OwningBinary<object::ObjectFile> O,
RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver,
bool ProcessAllSections,
unique_function<
Error(const object::ObjectFile &Obj,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObj,
std::map<StringRef, JITEvaluatedSymbol>)>
unique_function<Error(const object::ObjectFile &Obj,
RuntimeDyld::LoadedObjectInfo &LoadedObj,
std::map<StringRef, JITEvaluatedSymbol>)>
OnLoaded,
unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
unique_function<void(object::OwningBinary<object::ObjectFile>,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)>
OnEmitted) {
RuntimeDyld RTDyld(MemMgr, Resolver);
@ -1432,17 +1435,17 @@ void jitLinkForORC(
auto Info = RTDyld.loadObject(*O.getBinary());
if (RTDyld.hasError()) {
OnEmitted(std::move(O), make_error<StringError>(RTDyld.getErrorString(),
inconvertibleErrorCode()));
OnEmitted(std::move(O), std::move(Info),
make_error<StringError>(RTDyld.getErrorString(),
inconvertibleErrorCode()));
return;
}
if (auto Err =
OnLoaded(*O.getBinary(), std::move(Info), RTDyld.getSymbolTable()))
OnEmitted(std::move(O), std::move(Err));
if (auto Err = OnLoaded(*O.getBinary(), *Info, RTDyld.getSymbolTable()))
OnEmitted(std::move(O), std::move(Info), std::move(Err));
RuntimeDyldImpl::finalizeAsync(std::move(RTDyld.Dyld), std::move(OnEmitted),
std::move(O));
std::move(O), std::move(Info));
}
} // end namespace llvm

View File

@ -535,9 +535,12 @@ public:
static void finalizeAsync(
std::unique_ptr<RuntimeDyldImpl> This,
unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
unique_function<void(object::OwningBinary<object::ObjectFile>,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>,
Error)>
OnEmitted,
object::OwningBinary<object::ObjectFile> O);
object::OwningBinary<object::ObjectFile> O,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info);
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);

View File

@ -482,12 +482,11 @@ LLVMJITLinkObjectLinkingLayer::LLVMJITLinkObjectLinkingLayer(
Session &S, JITLinkMemoryManager &MemMgr)
: ObjectLinkingLayer(S.ES, MemMgr), S(S) {}
Error LLVMJITLinkObjectLinkingLayer::add(JITDylib &JD,
std::unique_ptr<MemoryBuffer> O,
VModuleKey K) {
Error LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT,
std::unique_ptr<MemoryBuffer> O) {
if (S.HarnessFiles.empty() || S.HarnessFiles.count(O->getBufferIdentifier()))
return ObjectLinkingLayer::add(JD, std::move(O), std::move(K));
return ObjectLinkingLayer::add(std::move(RT), std::move(O));
// Use getObjectSymbolInfo to compute the init symbol, but ignore
// the symbols field. We'll handle that manually to include promotion.
@ -556,9 +555,10 @@ Error LLVMJITLinkObjectLinkingLayer::add(JITDylib &JD,
}
auto MU = std::make_unique<BasicObjectLayerMaterializationUnit>(
*this, K, std::move(O), std::move(SymbolFlags), std::move(InitSymbol));
*this, std::move(O), std::move(SymbolFlags), std::move(InitSymbol));
return JD.define(std::move(MU));
auto &JD = RT->getJITDylib();
return JD.define(std::move(MU), std::move(RT));
}
class PhonyExternalsGenerator : public JITDylib::DefinitionGenerator {
@ -586,6 +586,11 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT) {
return std::move(S);
}
Session::~Session() {
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
}
// FIXME: Move to createJITDylib if/when we start using Platform support in
// llvm-jitlink.
Session::Session(Triple TT, uint64_t PageSize, Error &Err)
@ -603,6 +608,15 @@ Session::Session(Triple TT, uint64_t PageSize, Error &Err)
S.modifyPassConfig(TT, PassConfig);
}
Error notifyFailed(MaterializationResponsibility &MR) override {
return Error::success();
}
Error notifyRemovingResources(ResourceKey K) override {
return Error::success();
}
void notifyTransferringResources(ResourceKey DstKey,
ResourceKey SrcKey) override {}
private:
Session &S;
};
@ -618,7 +632,7 @@ Session::Session(Triple TT, uint64_t PageSize, Error &Err)
if (!NoExec && !TT.isOSWindows())
ObjLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
std::make_unique<InProcessEHFrameRegistrar>()));
ES, std::make_unique<InProcessEHFrameRegistrar>()));
ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));

View File

@ -33,11 +33,13 @@ struct Session;
/// ObjectLinkingLayer with additional support for symbol promotion.
class LLVMJITLinkObjectLinkingLayer : public orc::ObjectLinkingLayer {
public:
using orc::ObjectLinkingLayer::add;
LLVMJITLinkObjectLinkingLayer(Session &S,
jitlink::JITLinkMemoryManager &MemMgr);
Error add(orc::JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
orc::VModuleKey K = orc::VModuleKey()) override;
Error add(orc::ResourceTrackerSP RT,
std::unique_ptr<MemoryBuffer> O) override;
private:
Session &S;
@ -50,6 +52,8 @@ struct Session {
LLVMJITLinkObjectLinkingLayer ObjLayer;
std::vector<orc::JITDylib *> JDSearchOrder;
~Session();
static Expected<std::unique_ptr<Session>> Create(Triple TT);
void dumpSessionInfo(raw_ostream &OS);
void modifyPassConfig(const Triple &FTT,

View File

@ -18,6 +18,7 @@ add_llvm_unittest(OrcJITTests
LazyCallThroughAndReexportsTest.cpp
OrcTestCommon.cpp
QueueChannel.cpp
ResourceTrackerTest.cpp
RPCUtilsTest.cpp
RTDyldObjectLinkingLayerTest.cpp
SymbolStringPoolTest.cpp

View File

@ -1242,7 +1242,7 @@ TEST_F(CoreAPIsStandardTest, TestGetRequestedSymbolsAndReplace) {
BarMaterialized = true;
});
R->replace(std::move(NewMU));
cantFail(R->replace(std::move(NewMU)));
cantFail(R->notifyResolved(SymbolMap({{Foo, FooSym}})));
cantFail(R->notifyEmitted());
@ -1272,7 +1272,7 @@ TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) {
auto MU = std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
auto R2 = R->delegate({Bar});
auto R2 = cantFail(R->delegate({Bar}));
cantFail(R->notifyResolved({{Foo, FooSym}}));
cantFail(R->notifyEmitted());
@ -1333,7 +1333,7 @@ TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) {
cantFail(FooR->notifyEmitted());
}
static bool linkOrdersEqual(const std::vector<std::shared_ptr<JITDylib>> &LHS,
static bool linkOrdersEqual(const std::vector<JITDylibSP> &LHS,
ArrayRef<JITDylib *> RHS) {
if (LHS.size() != RHS.size())
return false;
@ -1367,23 +1367,21 @@ TEST(JITDylibTest, GetDFSLinkOrderTree) {
LibB.setLinkOrder(makeJITDylibSearchOrder({&LibD, &LibE}));
LibC.setLinkOrder(makeJITDylibSearchOrder({&LibF}));
auto DFSOrderFromB = JITDylib::getDFSLinkOrder({LibB.shared_from_this()});
auto DFSOrderFromB = JITDylib::getDFSLinkOrder({&LibB});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB, {&LibB, &LibD, &LibE}))
<< "Incorrect DFS link order for LibB";
auto DFSOrderFromA = JITDylib::getDFSLinkOrder({LibA.shared_from_this()});
auto DFSOrderFromA = JITDylib::getDFSLinkOrder({&LibA});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA,
{&LibA, &LibB, &LibD, &LibE, &LibC, &LibF}))
<< "Incorrect DFS link order for libA";
auto DFSOrderFromAB = JITDylib::getDFSLinkOrder(
{LibA.shared_from_this(), LibB.shared_from_this()});
auto DFSOrderFromAB = JITDylib::getDFSLinkOrder({&LibA, &LibB});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromAB,
{&LibA, &LibB, &LibD, &LibE, &LibC, &LibF}))
<< "Incorrect DFS link order for { libA, libB }";
auto DFSOrderFromBA = JITDylib::getDFSLinkOrder(
{LibB.shared_from_this(), LibA.shared_from_this()});
auto DFSOrderFromBA = JITDylib::getDFSLinkOrder({&LibB, &LibA});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromBA,
{&LibB, &LibD, &LibE, &LibA, &LibC, &LibF}))
<< "Incorrect DFS link order for { libB, libA }";
@ -1406,7 +1404,7 @@ TEST(JITDylibTest, GetDFSLinkOrderDiamond) {
LibB.setLinkOrder(makeJITDylibSearchOrder({&LibD}));
LibC.setLinkOrder(makeJITDylibSearchOrder({&LibD}));
auto DFSOrderFromA = JITDylib::getDFSLinkOrder({LibA.shared_from_this()});
auto DFSOrderFromA = JITDylib::getDFSLinkOrder({&LibA});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA, {&LibA, &LibB, &LibD, &LibC}))
<< "Incorrect DFS link order for libA";
}
@ -1426,15 +1424,15 @@ TEST(JITDylibTest, GetDFSLinkOrderCycle) {
LibB.setLinkOrder(makeJITDylibSearchOrder({&LibC}));
LibC.setLinkOrder(makeJITDylibSearchOrder({&LibA}));
auto DFSOrderFromA = JITDylib::getDFSLinkOrder({LibA.shared_from_this()});
auto DFSOrderFromA = JITDylib::getDFSLinkOrder({&LibA});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromA, {&LibA, &LibB, &LibC}))
<< "Incorrect DFS link order for libA";
auto DFSOrderFromB = JITDylib::getDFSLinkOrder({LibB.shared_from_this()});
auto DFSOrderFromB = JITDylib::getDFSLinkOrder({&LibB});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromB, {&LibB, &LibC, &LibA}))
<< "Incorrect DFS link order for libB";
auto DFSOrderFromC = JITDylib::getDFSLinkOrder({LibC.shared_from_this()});
auto DFSOrderFromC = JITDylib::getDFSLinkOrder({&LibC});
EXPECT_TRUE(linkOrdersEqual(DFSOrderFromC, {&LibC, &LibA, &LibB}))
<< "Incorrect DFS link order for libC";
}

View File

@ -44,6 +44,12 @@ namespace orc {
// linkage and non-hidden visibility.
// (5) V -- A JITDylib associated with ES.
class CoreAPIsBasedStandardTest : public testing::Test {
public:
~CoreAPIsBasedStandardTest() {
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
}
protected:
std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
ExecutionSession ES{SSP};
@ -96,8 +102,7 @@ public:
orc::SymbolStringPtr InitSym = nullptr,
DiscardFunction Discard = DiscardFunction(),
DestructorFunction Destructor = DestructorFunction())
: MaterializationUnit(std::move(SymbolFlags), std::move(InitSym),
orc::VModuleKey()),
: MaterializationUnit(std::move(SymbolFlags), std::move(InitSym)),
Materialize(std::move(Materialize)), Discard(std::move(Discard)),
Destructor(std::move(Destructor)) {}
@ -157,6 +162,11 @@ public:
}
};
~OrcExecutionTest() {
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
}
protected:
orc::ExecutionSession ES;
LLVMContext Context;

View File

@ -59,11 +59,14 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
};
ObjLayer.setProcessAllSections(ProcessAllSections);
cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule()));
cantFail(ObjLayer.add(JD, std::move(Obj)));
ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing,
NoDependenciesToRegister);
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
return DebugSectionSeen;
}
@ -159,12 +162,15 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
cantFail(CompileLayer.add(JD, std::move(M)));
ES.lookup(
LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
SymbolState::Resolved,
[](Expected<SymbolMap> R) { cantFail(std::move(R)); },
NoDependenciesToRegister);
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
}
TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
@ -226,12 +232,15 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
cantFail(CompileLayer.add(JD, std::move(M)));
ES.lookup(
LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
SymbolState::Resolved,
[](Expected<SymbolMap> R) { cantFail(std::move(R)); },
NoDependenciesToRegister);
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
}
} // end anonymous namespace

View File

@ -0,0 +1,457 @@
//===------ ResourceTrackerTest.cpp - Unit tests ResourceTracker API
//-------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "OrcTestCommon.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/Testing/Support/Error.h"
using namespace llvm;
using namespace llvm::orc;
class ResourceTrackerStandardTest : public CoreAPIsBasedStandardTest {};
namespace {
template <typename ResourceT = unsigned>
class SimpleResourceManager : public ResourceManager {
public:
using HandleRemoveFunction = unique_function<Error(ResourceKey)>;
using HandleTransferFunction =
unique_function<void(ResourceKey, ResourceKey)>;
using RecordedResourcesMap = DenseMap<ResourceKey, ResourceT>;
SimpleResourceManager(
ExecutionSession &ES,
HandleRemoveFunction HandleRemove = HandleRemoveFunction(),
HandleTransferFunction HandleTransfer = HandleTransferFunction())
: ES(ES), HandleRemove(std::move(HandleRemove)),
HandleTransfer(std::move(HandleTransfer)) {
// If HandleRemvoe is not supplied then use the default.
if (!this->HandleRemove)
this->HandleRemove = [&](ResourceKey K) -> Error {
ES.runSessionLocked([&] { removeResource(K); });
return Error::success();
};
// If HandleTransfer is not supplied then use the default.
if (!this->HandleTransfer)
this->HandleTransfer = [this](ResourceKey DstKey, ResourceKey SrcKey) {
transferResources(DstKey, SrcKey);
};
ES.registerResourceManager(*this);
}
SimpleResourceManager(const SimpleResourceManager &) = delete;
SimpleResourceManager &operator=(const SimpleResourceManager &) = delete;
SimpleResourceManager(SimpleResourceManager &&) = delete;
SimpleResourceManager &operator=(SimpleResourceManager &&) = delete;
~SimpleResourceManager() { ES.deregisterResourceManager(*this); }
/// Create an association between the given key and resource.
template <typename MergeOp = std::plus<ResourceT>>
void recordResource(ResourceKey K, ResourceT Val = ResourceT(),
MergeOp Merge = MergeOp()) {
auto Tmp = std::move(Resources[K]);
Resources[K] = Merge(std::move(Tmp), std::move(Val));
}
/// Remove the resource associated with K from the map if present.
void removeResource(ResourceKey K) { Resources.erase(K); }
/// Transfer resources from DstKey to SrcKey.
template <typename MergeOp = std::plus<ResourceT>>
void transferResources(ResourceKey DstKey, ResourceKey SrcKey,
MergeOp Merge = MergeOp()) {
auto &DstResourceRef = Resources[DstKey];
ResourceT DstResources;
std::swap(DstResourceRef, DstResources);
auto SI = Resources.find(SrcKey);
assert(SI != Resources.end() && "No resource associated with SrcKey");
DstResourceRef = Merge(std::move(DstResources), std::move(SI->second));
Resources.erase(SI);
}
/// Return a reference to the Resources map.
RecordedResourcesMap &getRecordedResources() { return Resources; }
const RecordedResourcesMap &getRecordedResources() const { return Resources; }
Error handleRemoveResources(ResourceKey K) override {
return HandleRemove(K);
}
void handleTransferResources(ResourceKey DstKey,
ResourceKey SrcKey) override {
HandleTransfer(DstKey, SrcKey);
}
static void transferNotAllowed(ResourceKey DstKey, ResourceKey SrcKey) {
llvm_unreachable("Resource transfer not allowed");
}
private:
ExecutionSession &ES;
HandleRemoveFunction HandleRemove;
HandleTransferFunction HandleTransfer;
RecordedResourcesMap Resources;
};
TEST_F(ResourceTrackerStandardTest,
BasicDefineAndRemoveAllBeforeMaterializing) {
bool ResourceManagerGotRemove = false;
SimpleResourceManager<> SRM(ES, [&](ResourceKey K) -> Error {
ResourceManagerGotRemove = true;
EXPECT_EQ(SRM.getRecordedResources().size(), 0U)
<< "Unexpected resources recorded";
SRM.removeResource(K);
return Error::success();
});
bool MaterializationUnitDestroyed = false;
auto MU = std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
llvm_unreachable("Never called");
},
nullptr, SimpleMaterializationUnit::DiscardFunction(),
[&]() { MaterializationUnitDestroyed = true; });
auto RT = JD.createResourceTracker();
cantFail(JD.define(std::move(MU), RT));
cantFail(RT->remove());
auto SymFlags = cantFail(JD.lookupFlags(
LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly,
SymbolLookupSet(Foo)));
EXPECT_EQ(SymFlags.size(), 0U)
<< "Symbols should have been removed from the symbol table";
EXPECT_TRUE(ResourceManagerGotRemove)
<< "ResourceManager did not receive handleRemoveResources";
EXPECT_TRUE(MaterializationUnitDestroyed)
<< "MaterializationUnit not destroyed in response to removal";
}
TEST_F(ResourceTrackerStandardTest, BasicDefineAndRemoveAllAfterMaterializing) {
bool ResourceManagerGotRemove = false;
SimpleResourceManager<> SRM(ES, [&](ResourceKey K) -> Error {
ResourceManagerGotRemove = true;
EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
<< "Unexpected number of resources recorded";
EXPECT_EQ(SRM.getRecordedResources().count(K), 1U)
<< "Unexpected recorded resource";
SRM.removeResource(K);
return Error::success();
});
auto MU = std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
cantFail(R->withResourceKeyDo(
[&](ResourceKey K) { SRM.recordResource(K); }));
cantFail(R->notifyResolved({{Foo, FooSym}}));
cantFail(R->notifyEmitted());
});
auto RT = JD.createResourceTracker();
cantFail(JD.define(std::move(MU), RT));
cantFail(ES.lookup({&JD}, Foo));
cantFail(RT->remove());
auto SymFlags = cantFail(JD.lookupFlags(
LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly,
SymbolLookupSet(Foo)));
EXPECT_EQ(SymFlags.size(), 0U)
<< "Symbols should have been removed from the symbol table";
EXPECT_TRUE(ResourceManagerGotRemove)
<< "ResourceManager did not receive handleRemoveResources";
}
TEST_F(ResourceTrackerStandardTest, BasicDefineAndRemoveAllWhileMaterializing) {
bool ResourceManagerGotRemove = false;
SimpleResourceManager<> SRM(ES, [&](ResourceKey K) -> Error {
ResourceManagerGotRemove = true;
EXPECT_EQ(SRM.getRecordedResources().size(), 0U)
<< "Unexpected resources recorded";
SRM.removeResource(K);
return Error::success();
});
std::unique_ptr<MaterializationResponsibility> MR;
auto MU = std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
MR = std::move(R);
});
auto RT = JD.createResourceTracker();
cantFail(JD.define(std::move(MU), RT));
ES.lookup(
LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
SymbolState::Ready,
[](Expected<SymbolMap> Result) {
EXPECT_THAT_EXPECTED(Result, Failed<FailedToMaterialize>())
<< "Lookup failed unexpectedly";
},
NoDependenciesToRegister);
cantFail(RT->remove());
auto SymFlags = cantFail(JD.lookupFlags(
LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly,
SymbolLookupSet(Foo)));
EXPECT_EQ(SymFlags.size(), 0U)
<< "Symbols should have been removed from the symbol table";
EXPECT_TRUE(ResourceManagerGotRemove)
<< "ResourceManager did not receive handleRemoveResources";
EXPECT_THAT_ERROR(MR->withResourceKeyDo([](ResourceKey K) {
ADD_FAILURE() << "Should not reach withResourceKeyDo body for removed key";
}),
Failed<ResourceTrackerDefunct>())
<< "withResourceKeyDo on MR with removed tracker should have failed";
EXPECT_THAT_ERROR(MR->notifyResolved({{Foo, FooSym}}),
Failed<ResourceTrackerDefunct>())
<< "notifyResolved on MR with removed tracker should have failed";
MR->failMaterialization();
}
TEST_F(ResourceTrackerStandardTest, JITDylibClear) {
SimpleResourceManager<> SRM(ES);
// Add materializer for Foo.
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
cantFail(R->withResourceKeyDo(
[&](ResourceKey K) { ++SRM.getRecordedResources()[K]; }));
cantFail(R->notifyResolved({{Foo, FooSym}}));
cantFail(R->notifyEmitted());
})));
// Add materializer for Bar.
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
cantFail(R->withResourceKeyDo(
[&](ResourceKey K) { ++SRM.getRecordedResources()[K]; }));
cantFail(R->notifyResolved({{Bar, BarSym}}));
cantFail(R->notifyEmitted());
})));
EXPECT_TRUE(SRM.getRecordedResources().empty())
<< "Expected no resources recorded yet.";
cantFail(
ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar})));
auto JDResourceKey = JD.getDefaultResourceTracker()->getKeyUnsafe();
EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
<< "Expected exactly one entry (for JD's ResourceKey)";
EXPECT_EQ(SRM.getRecordedResources().count(JDResourceKey), 1U)
<< "Expected an entry for JD's ResourceKey";
EXPECT_EQ(SRM.getRecordedResources()[JDResourceKey], 2U)
<< "Expected value of 2 for JD's ResourceKey "
"(+1 for each of Foo and Bar)";
cantFail(JD.clear());
EXPECT_TRUE(SRM.getRecordedResources().empty())
<< "Expected no resources recorded after clear";
}
TEST_F(ResourceTrackerStandardTest,
BasicDefineAndExplicitTransferBeforeMaterializing) {
bool ResourceManagerGotTransfer = false;
SimpleResourceManager<> SRM(
ES,
[&](ResourceKey K) -> Error {
SRM.removeResource(K);
return Error::success();
},
[&](ResourceKey DstKey, ResourceKey SrcKey) {
ResourceManagerGotTransfer = true;
auto &RR = SRM.getRecordedResources();
EXPECT_EQ(RR.size(), 0U) << "Expected no resources recorded yet";
});
auto MakeMU = [&](SymbolStringPtr Name, JITEvaluatedSymbol Sym) {
return std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Name, Sym.getFlags()}}),
[=, &SRM](std::unique_ptr<MaterializationResponsibility> R) {
cantFail(R->withResourceKeyDo(
[&](ResourceKey K) { SRM.recordResource(K); }));
cantFail(R->notifyResolved({{Name, Sym}}));
cantFail(R->notifyEmitted());
});
};
auto FooRT = JD.createResourceTracker();
cantFail(JD.define(MakeMU(Foo, FooSym), FooRT));
auto BarRT = JD.createResourceTracker();
cantFail(JD.define(MakeMU(Bar, BarSym), BarRT));
BarRT->transferTo(*FooRT);
EXPECT_TRUE(ResourceManagerGotTransfer)
<< "ResourceManager did not receive transfer";
EXPECT_TRUE(BarRT->isDefunct()) << "BarRT should now be defunct";
cantFail(
ES.lookup(makeJITDylibSearchOrder({&JD}), SymbolLookupSet({Foo, Bar})));
EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
<< "Expected exactly one entry (for FooRT's Key)";
EXPECT_EQ(SRM.getRecordedResources().count(FooRT->getKeyUnsafe()), 1U)
<< "Expected an entry for FooRT's ResourceKey";
EXPECT_EQ(SRM.getRecordedResources().count(BarRT->getKeyUnsafe()), 0U)
<< "Expected no entry for BarRT's ResourceKey";
// We need to explicitly destroy FooRT or its resources will be implicitly
// transferred to the default tracker triggering a second call to our
// transfer function above (which expects only one call).
cantFail(FooRT->remove());
}
TEST_F(ResourceTrackerStandardTest,
BasicDefineAndExplicitTransferAfterMaterializing) {
bool ResourceManagerGotTransfer = false;
SimpleResourceManager<> SRM(
ES,
[&](ResourceKey K) -> Error {
SRM.removeResource(K);
return Error::success();
},
[&](ResourceKey DstKey, ResourceKey SrcKey) {
ResourceManagerGotTransfer = true;
SRM.transferResources(DstKey, SrcKey);
});
auto MakeMU = [&](SymbolStringPtr Name, JITEvaluatedSymbol Sym) {
return std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Name, Sym.getFlags()}}),
[=, &SRM](std::unique_ptr<MaterializationResponsibility> R) {
cantFail(R->withResourceKeyDo(
[&](ResourceKey K) { SRM.recordResource(K, 1); }));
cantFail(R->notifyResolved({{Name, Sym}}));
cantFail(R->notifyEmitted());
});
};
auto FooRT = JD.createResourceTracker();
cantFail(JD.define(MakeMU(Foo, FooSym), FooRT));
auto BarRT = JD.createResourceTracker();
cantFail(JD.define(MakeMU(Bar, BarSym), BarRT));
EXPECT_EQ(SRM.getRecordedResources().size(), 0U)
<< "Expected no recorded resources yet";
cantFail(
ES.lookup(makeJITDylibSearchOrder({&JD}), SymbolLookupSet({Foo, Bar})));
EXPECT_EQ(SRM.getRecordedResources().size(), 2U)
<< "Expected recorded resources for both Foo and Bar";
BarRT->transferTo(*FooRT);
EXPECT_TRUE(ResourceManagerGotTransfer)
<< "ResourceManager did not receive transfer";
EXPECT_TRUE(BarRT->isDefunct()) << "BarRT should now be defunct";
EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
<< "Expected recorded resources for Foo only";
EXPECT_EQ(SRM.getRecordedResources().count(FooRT->getKeyUnsafe()), 1U)
<< "Expected recorded resources for Foo";
EXPECT_EQ(SRM.getRecordedResources()[FooRT->getKeyUnsafe()], 2U)
<< "Expected resources value for for Foo to be '2'";
}
TEST_F(ResourceTrackerStandardTest,
BasicDefineAndExplicitTransferWhileMaterializing) {
bool ResourceManagerGotTransfer = false;
SimpleResourceManager<> SRM(
ES,
[&](ResourceKey K) -> Error {
SRM.removeResource(K);
return Error::success();
},
[&](ResourceKey DstKey, ResourceKey SrcKey) {
ResourceManagerGotTransfer = true;
SRM.transferResources(DstKey, SrcKey);
});
auto FooRT = JD.createResourceTracker();
std::unique_ptr<MaterializationResponsibility> FooMR;
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
[&](std::unique_ptr<MaterializationResponsibility> R) {
FooMR = std::move(R);
}),
FooRT));
auto BarRT = JD.createResourceTracker();
ES.lookup(
LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
SymbolState::Ready,
[](Expected<SymbolMap> Result) { cantFail(Result.takeError()); },
NoDependenciesToRegister);
cantFail(FooMR->withResourceKeyDo([&](ResourceKey K) {
EXPECT_EQ(FooRT->getKeyUnsafe(), K)
<< "Expected FooRT's ResourceKey for Foo here";
SRM.recordResource(K, 1);
}));
EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
<< "Expected one recorded resource here";
EXPECT_EQ(SRM.getRecordedResources()[FooRT->getKeyUnsafe()], 1U)
<< "Expected Resource value for FooRT to be '1' here";
FooRT->transferTo(*BarRT);
EXPECT_TRUE(ResourceManagerGotTransfer)
<< "Expected resource manager to receive handleTransferResources call";
cantFail(FooMR->withResourceKeyDo([&](ResourceKey K) {
EXPECT_EQ(BarRT->getKeyUnsafe(), K)
<< "Expected BarRT's ResourceKey for Foo here";
SRM.recordResource(K, 1);
}));
EXPECT_EQ(SRM.getRecordedResources().size(), 1U)
<< "Expected one recorded resource here";
EXPECT_EQ(SRM.getRecordedResources().count(BarRT->getKeyUnsafe()), 1U)
<< "Expected RecordedResources to contain an entry for BarRT";
EXPECT_EQ(SRM.getRecordedResources()[BarRT->getKeyUnsafe()], 2U)
<< "Expected Resource value for BarRT to be '2' here";
cantFail(FooMR->notifyResolved({{Foo, FooSym}}));
cantFail(FooMR->notifyEmitted());
}
} // namespace