Revert "[ORC][llvm-jitlink] Add SimpleLazyReexportsSpeculator, use in llvm-jitlink."
This reverts commit 6d72bf4760 while I fix bot failures.
This commit is contained in:
@@ -65,8 +65,7 @@ private:
|
||||
Expected<std::unique_ptr<LazyReexportsManager>>
|
||||
createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,
|
||||
RedirectableSymbolManager &RSMgr,
|
||||
JITDylib &PlatformJD,
|
||||
LazyReexportsManager::Listener *L = nullptr);
|
||||
JITDylib &PlatformJD);
|
||||
|
||||
} // namespace llvm::orc
|
||||
|
||||
|
||||
@@ -179,37 +179,6 @@ class LazyReexportsManager : public ResourceManager {
|
||||
lazyReexports(LazyReexportsManager &, SymbolAliasMap);
|
||||
|
||||
public:
|
||||
struct CallThroughInfo {
|
||||
JITDylibSP JD;
|
||||
SymbolStringPtr Name;
|
||||
SymbolStringPtr BodyName;
|
||||
};
|
||||
|
||||
class Listener {
|
||||
public:
|
||||
using CallThroughInfo = LazyReexportsManager::CallThroughInfo;
|
||||
|
||||
virtual ~Listener();
|
||||
|
||||
/// Called under the session lock when new lazy reexports are created.
|
||||
virtual void onLazyReexportsCreated(JITDylib &JD, ResourceKey K,
|
||||
const SymbolAliasMap &Reexports) = 0;
|
||||
|
||||
/// Called under the session lock when lazy reexports have their ownership
|
||||
/// transferred to a new ResourceKey.
|
||||
virtual void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK,
|
||||
ResourceKey SrcK) = 0;
|
||||
|
||||
/// Called under the session lock when lazy reexports are removed.
|
||||
virtual Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K) = 0;
|
||||
|
||||
/// Called outside the session lock when a lazy reexport is called.
|
||||
/// NOTE: Since this is called outside the session lock there is a chance
|
||||
/// that the reexport referred to has already been removed. Listeners
|
||||
/// must be prepared to handle requests for stale reexports.
|
||||
virtual void onLazyReexportCalled(const CallThroughInfo &CTI) = 0;
|
||||
};
|
||||
|
||||
using OnTrampolinesReadyFn = unique_function<void(
|
||||
Expected<std::vector<ExecutorSymbolDef>> EntryAddrs)>;
|
||||
using EmitTrampolinesFn =
|
||||
@@ -220,7 +189,7 @@ public:
|
||||
/// This will work both in-process and out-of-process.
|
||||
static Expected<std::unique_ptr<LazyReexportsManager>>
|
||||
Create(EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr,
|
||||
JITDylib &PlatformJD, Listener *L = nullptr);
|
||||
JITDylib &PlatformJD);
|
||||
|
||||
LazyReexportsManager(LazyReexportsManager &&) = delete;
|
||||
LazyReexportsManager &operator=(LazyReexportsManager &&) = delete;
|
||||
@@ -230,6 +199,12 @@ public:
|
||||
ResourceKey SrcK) override;
|
||||
|
||||
private:
|
||||
struct CallThroughInfo {
|
||||
SymbolStringPtr Name;
|
||||
SymbolStringPtr BodyName;
|
||||
JITDylibSP JD;
|
||||
};
|
||||
|
||||
class MU;
|
||||
class Plugin;
|
||||
|
||||
@@ -238,7 +213,7 @@ private:
|
||||
|
||||
LazyReexportsManager(EmitTrampolinesFn EmitTrampolines,
|
||||
RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD,
|
||||
Listener *L, Error &Err);
|
||||
Error &Err);
|
||||
|
||||
std::unique_ptr<MaterializationUnit>
|
||||
createLazyReexports(SymbolAliasMap Reexports);
|
||||
@@ -254,7 +229,6 @@ private:
|
||||
ExecutionSession &ES;
|
||||
EmitTrampolinesFn EmitTrampolines;
|
||||
RedirectableSymbolManager &RSMgr;
|
||||
Listener *L;
|
||||
|
||||
DenseMap<ResourceKey, std::vector<ExecutorAddr>> KeyToReentryAddrs;
|
||||
DenseMap<ExecutorAddr, CallThroughInfo> CallThroughs;
|
||||
@@ -268,66 +242,6 @@ lazyReexports(LazyReexportsManager &LRM, SymbolAliasMap Reexports) {
|
||||
return LRM.createLazyReexports(std::move(Reexports));
|
||||
}
|
||||
|
||||
class SimpleLazyReexportsSpeculator : public LazyReexportsManager::Listener {
|
||||
friend std::shared_ptr<SimpleLazyReexportsSpeculator> std::make_shared();
|
||||
|
||||
public:
|
||||
using RecordExecutionFunction =
|
||||
unique_function<void(const CallThroughInfo &CTI)>;
|
||||
|
||||
static std::shared_ptr<SimpleLazyReexportsSpeculator>
|
||||
Create(ExecutionSession &ES, RecordExecutionFunction RecordExec = {}) {
|
||||
class make_shared_helper : public SimpleLazyReexportsSpeculator {
|
||||
public:
|
||||
make_shared_helper(ExecutionSession &ES,
|
||||
RecordExecutionFunction RecordExec)
|
||||
: SimpleLazyReexportsSpeculator(ES, std::move(RecordExec)) {}
|
||||
};
|
||||
|
||||
auto Instance =
|
||||
std::make_shared<make_shared_helper>(ES, std::move(RecordExec));
|
||||
Instance->WeakThis = Instance;
|
||||
return Instance;
|
||||
}
|
||||
|
||||
SimpleLazyReexportsSpeculator(SimpleLazyReexportsSpeculator &&) = delete;
|
||||
SimpleLazyReexportsSpeculator &
|
||||
operator=(SimpleLazyReexportsSpeculator &&) = delete;
|
||||
~SimpleLazyReexportsSpeculator() override;
|
||||
|
||||
void onLazyReexportsCreated(JITDylib &JD, ResourceKey K,
|
||||
const SymbolAliasMap &Reexports) override;
|
||||
|
||||
void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK,
|
||||
ResourceKey SrcK) override;
|
||||
|
||||
Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K) override;
|
||||
|
||||
void onLazyReexportCalled(const CallThroughInfo &CTI) override;
|
||||
|
||||
void addSpeculationSuggestions(
|
||||
std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions);
|
||||
|
||||
private:
|
||||
SimpleLazyReexportsSpeculator(ExecutionSession &ES,
|
||||
RecordExecutionFunction RecordExec)
|
||||
: ES(ES), RecordExec(std::move(RecordExec)) {}
|
||||
|
||||
bool doNextSpeculativeLookup();
|
||||
|
||||
class SpeculateTask;
|
||||
|
||||
using KeyToFunctionBodiesMap =
|
||||
DenseMap<ResourceKey, std::vector<SymbolStringPtr>>;
|
||||
|
||||
ExecutionSession &ES;
|
||||
RecordExecutionFunction RecordExec;
|
||||
std::weak_ptr<SimpleLazyReexportsSpeculator> WeakThis;
|
||||
DenseMap<JITDylib *, KeyToFunctionBodiesMap> LazyReexports;
|
||||
std::deque<std::pair<std::string, SymbolStringPtr>> SpeculateSuggestions;
|
||||
bool SpeculateTaskActive = false;
|
||||
};
|
||||
|
||||
} // End namespace orc
|
||||
} // End namespace llvm
|
||||
|
||||
|
||||
@@ -92,16 +92,6 @@ makeGenericNamedTask(FnT &&Fn, const char *Desc = nullptr) {
|
||||
Desc);
|
||||
}
|
||||
|
||||
/// IdleTask can be used as the basis for low-priority tasks, e.g. speculative
|
||||
/// lookup.
|
||||
class IdleTask : public RTTIExtends<IdleTask, Task> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
private:
|
||||
void anchor() override;
|
||||
};
|
||||
|
||||
/// Abstract base for classes that dispatch ORC Tasks.
|
||||
class TaskDispatcher {
|
||||
public:
|
||||
@@ -128,13 +118,9 @@ public:
|
||||
DynamicThreadPoolTaskDispatcher(
|
||||
std::optional<size_t> MaxMaterializationThreads)
|
||||
: MaxMaterializationThreads(MaxMaterializationThreads) {}
|
||||
|
||||
void dispatch(std::unique_ptr<Task> T) override;
|
||||
void shutdown() override;
|
||||
private:
|
||||
bool canRunMaterializationTaskNow();
|
||||
bool canRunIdleTaskNow();
|
||||
|
||||
std::mutex DispatchMutex;
|
||||
bool Shutdown = false;
|
||||
size_t Outstanding = 0;
|
||||
@@ -143,7 +129,6 @@ private:
|
||||
std::optional<size_t> MaxMaterializationThreads;
|
||||
size_t NumMaterializationThreads = 0;
|
||||
std::deque<std::unique_ptr<Task>> MaterializationTaskQueue;
|
||||
std::deque<std::unique_ptr<Task>> IdleTaskQueue;
|
||||
};
|
||||
|
||||
#endif // LLVM_ENABLE_THREADS
|
||||
|
||||
@@ -173,8 +173,7 @@ void JITLinkReentryTrampolines::emit(ResourceTrackerSP RT,
|
||||
Expected<std::unique_ptr<LazyReexportsManager>>
|
||||
createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,
|
||||
RedirectableSymbolManager &RSMgr,
|
||||
JITDylib &PlatformJD,
|
||||
LazyReexportsManager::Listener *L) {
|
||||
JITDylib &PlatformJD) {
|
||||
auto JLT = JITLinkReentryTrampolines::Create(ObjLinkingLayer);
|
||||
if (!JLT)
|
||||
return JLT.takeError();
|
||||
@@ -185,7 +184,7 @@ createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,
|
||||
OnTrampolinesReady) mutable {
|
||||
JLT->emit(std::move(RT), NumTrampolines, std::move(OnTrampolinesReady));
|
||||
},
|
||||
RSMgr, PlatformJD, L);
|
||||
RSMgr, PlatformJD);
|
||||
}
|
||||
|
||||
} // namespace llvm::orc
|
||||
|
||||
@@ -280,34 +280,31 @@ private:
|
||||
std::mutex M;
|
||||
};
|
||||
|
||||
LazyReexportsManager::Listener::~Listener() = default;
|
||||
|
||||
Expected<std::unique_ptr<LazyReexportsManager>>
|
||||
LazyReexportsManager::Create(EmitTrampolinesFn EmitTrampolines,
|
||||
RedirectableSymbolManager &RSMgr,
|
||||
JITDylib &PlatformJD, Listener *L) {
|
||||
JITDylib &PlatformJD) {
|
||||
Error Err = Error::success();
|
||||
std::unique_ptr<LazyReexportsManager> LRM(new LazyReexportsManager(
|
||||
std::move(EmitTrampolines), RSMgr, PlatformJD, L, Err));
|
||||
std::move(EmitTrampolines), RSMgr, PlatformJD, Err));
|
||||
if (Err)
|
||||
return std::move(Err);
|
||||
return std::move(LRM);
|
||||
}
|
||||
|
||||
Error LazyReexportsManager::handleRemoveResources(JITDylib &JD, ResourceKey K) {
|
||||
return JD.getExecutionSession().runSessionLocked([&]() -> Error {
|
||||
JD.getExecutionSession().runSessionLocked([&]() {
|
||||
auto I = KeyToReentryAddrs.find(K);
|
||||
if (I == KeyToReentryAddrs.end())
|
||||
return Error::success();
|
||||
|
||||
auto &ReentryAddrs = I->second;
|
||||
for (auto &ReentryAddr : ReentryAddrs) {
|
||||
assert(CallThroughs.count(ReentryAddr) && "CallTrhough missing");
|
||||
CallThroughs.erase(ReentryAddr);
|
||||
if (I != KeyToReentryAddrs.end()) {
|
||||
auto &ReentryAddrs = I->second;
|
||||
for (auto &ReentryAddr : ReentryAddrs) {
|
||||
assert(CallThroughs.count(ReentryAddr) && "CallTrhough missing");
|
||||
CallThroughs.erase(ReentryAddr);
|
||||
}
|
||||
KeyToReentryAddrs.erase(I);
|
||||
}
|
||||
KeyToReentryAddrs.erase(I);
|
||||
return L ? L->onLazyReexportsRemoved(JD, K) : Error::success();
|
||||
});
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void LazyReexportsManager::handleTransferResources(JITDylib &JD,
|
||||
@@ -326,17 +323,14 @@ void LazyReexportsManager::handleTransferResources(JITDylib &JD,
|
||||
DstAddrs.insert(DstAddrs.end(), SrcAddrs.begin(), SrcAddrs.end());
|
||||
KeyToReentryAddrs.erase(I);
|
||||
}
|
||||
if (L)
|
||||
L->onLazyReexportsTransfered(JD, DstK, SrcK);
|
||||
}
|
||||
}
|
||||
|
||||
LazyReexportsManager::LazyReexportsManager(EmitTrampolinesFn EmitTrampolines,
|
||||
RedirectableSymbolManager &RSMgr,
|
||||
JITDylib &PlatformJD, Listener *L,
|
||||
Error &Err)
|
||||
JITDylib &PlatformJD, Error &Err)
|
||||
: ES(PlatformJD.getExecutionSession()),
|
||||
EmitTrampolines(std::move(EmitTrampolines)), RSMgr(RSMgr), L(L) {
|
||||
EmitTrampolines(std::move(EmitTrampolines)), RSMgr(RSMgr) {
|
||||
|
||||
using namespace shared;
|
||||
|
||||
@@ -390,22 +384,17 @@ void LazyReexportsManager::emitRedirectableSymbols(
|
||||
Redirs[Name] = (*ReentryPoints)[I++];
|
||||
|
||||
I = 0;
|
||||
if (!Reexports.empty()) {
|
||||
if (auto Err = MR->withResourceKeyDo([&](ResourceKey K) {
|
||||
auto &JD = MR->getTargetJITDylib();
|
||||
auto &ReentryAddrsForK = KeyToReentryAddrs[K];
|
||||
for (auto &[Name, AI] : Reexports) {
|
||||
const auto &ReentryPoint = (*ReentryPoints)[I++];
|
||||
CallThroughs[ReentryPoint.getAddress()] = {&JD, Name, AI.Aliasee};
|
||||
ReentryAddrsForK.push_back(ReentryPoint.getAddress());
|
||||
}
|
||||
if (L)
|
||||
L->onLazyReexportsCreated(JD, K, Reexports);
|
||||
})) {
|
||||
MR->getExecutionSession().reportError(std::move(Err));
|
||||
MR->failMaterialization();
|
||||
return;
|
||||
}
|
||||
if (auto Err = MR->withResourceKeyDo([&](ResourceKey K) {
|
||||
for (auto &[Name, AI] : Reexports) {
|
||||
const auto &ReentryPoint = (*ReentryPoints)[I++];
|
||||
CallThroughs[ReentryPoint.getAddress()] = {Name, AI.Aliasee,
|
||||
&MR->getTargetJITDylib()};
|
||||
KeyToReentryAddrs[K].push_back(ReentryPoint.getAddress());
|
||||
}
|
||||
})) {
|
||||
MR->getExecutionSession().reportError(std::move(Err));
|
||||
MR->failMaterialization();
|
||||
return;
|
||||
}
|
||||
|
||||
RSMgr.emitRedirectableSymbols(std::move(MR), std::move(Redirs));
|
||||
@@ -426,9 +415,6 @@ void LazyReexportsManager::resolve(ResolveSendResultFn SendResult,
|
||||
LandingInfo = I->second;
|
||||
});
|
||||
|
||||
if (L)
|
||||
L->onLazyReexportCalled(LandingInfo);
|
||||
|
||||
SymbolInstance LandingSym(LandingInfo.JD, std::move(LandingInfo.BodyName));
|
||||
LandingSym.lookupAsync([this, JD = std::move(LandingInfo.JD),
|
||||
ReentryName = std::move(LandingInfo.Name),
|
||||
@@ -446,168 +432,5 @@ void LazyReexportsManager::resolve(ResolveSendResultFn SendResult,
|
||||
});
|
||||
}
|
||||
|
||||
class SimpleLazyReexportsSpeculator::SpeculateTask : public IdleTask {
|
||||
public:
|
||||
SpeculateTask(std::weak_ptr<SimpleLazyReexportsSpeculator> Speculator)
|
||||
: Speculator(std::move(Speculator)) {}
|
||||
|
||||
void printDescription(raw_ostream &OS) override {
|
||||
OS << "Speculative Lookup Task";
|
||||
}
|
||||
|
||||
void run() override {
|
||||
if (auto S = Speculator.lock())
|
||||
S->doNextSpeculativeLookup();
|
||||
}
|
||||
|
||||
private:
|
||||
std::weak_ptr<SimpleLazyReexportsSpeculator> Speculator;
|
||||
};
|
||||
|
||||
SimpleLazyReexportsSpeculator::~SimpleLazyReexportsSpeculator() {
|
||||
for (auto &[JD, _] : LazyReexports)
|
||||
JITDylibSP(JD)->Release();
|
||||
}
|
||||
|
||||
void SimpleLazyReexportsSpeculator::onLazyReexportsCreated(
|
||||
JITDylib &JD, ResourceKey K, const SymbolAliasMap &Reexports) {
|
||||
if (!LazyReexports.count(&JD))
|
||||
JD.Retain();
|
||||
auto &BodiesVec = LazyReexports[&JD][K];
|
||||
for (auto &[Name, AI] : Reexports)
|
||||
BodiesVec.push_back(AI.Aliasee);
|
||||
if (!SpeculateTaskActive) {
|
||||
SpeculateTaskActive = true;
|
||||
ES.dispatchTask(std::make_unique<SpeculateTask>(WeakThis));
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleLazyReexportsSpeculator::onLazyReexportsTransfered(
|
||||
JITDylib &JD, ResourceKey DstK, ResourceKey SrcK) {
|
||||
|
||||
auto I = LazyReexports.find(&JD);
|
||||
if (I == LazyReexports.end())
|
||||
return;
|
||||
|
||||
auto &MapForJD = I->second;
|
||||
auto J = MapForJD.find(SrcK);
|
||||
if (J == MapForJD.end())
|
||||
return;
|
||||
|
||||
// We have something to transfer.
|
||||
auto K = MapForJD.find(DstK);
|
||||
if (K == MapForJD.end()) {
|
||||
auto Tmp = std::move(J->second);
|
||||
MapForJD.erase(J);
|
||||
MapForJD[DstK] = std::move(Tmp);
|
||||
} else {
|
||||
auto &SrcNames = J->second;
|
||||
auto &DstNames = K->second;
|
||||
DstNames.insert(DstNames.end(), SrcNames.begin(), SrcNames.end());
|
||||
MapForJD.erase(J);
|
||||
}
|
||||
}
|
||||
|
||||
Error SimpleLazyReexportsSpeculator::onLazyReexportsRemoved(JITDylib &JD,
|
||||
ResourceKey K) {
|
||||
|
||||
auto I = LazyReexports.find(&JD);
|
||||
if (I == LazyReexports.end())
|
||||
return Error::success();
|
||||
|
||||
auto &MapForJD = I->second;
|
||||
MapForJD.erase(K);
|
||||
|
||||
if (MapForJD.empty()) {
|
||||
LazyReexports.erase(I);
|
||||
JD.Release();
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void SimpleLazyReexportsSpeculator::onLazyReexportCalled(
|
||||
const CallThroughInfo &CTI) {
|
||||
if (RecordExec)
|
||||
RecordExec(CTI);
|
||||
}
|
||||
|
||||
void SimpleLazyReexportsSpeculator::addSpeculationSuggestions(
|
||||
std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions) {
|
||||
ES.runSessionLocked([&]() {
|
||||
for (auto &[JDName, SymbolName] : NewSuggestions)
|
||||
SpeculateSuggestions.push_back(
|
||||
{std::move(JDName), std::move(SymbolName)});
|
||||
});
|
||||
}
|
||||
|
||||
bool SimpleLazyReexportsSpeculator::doNextSpeculativeLookup() {
|
||||
// Use existing speculation queue if available, otherwise take the next
|
||||
// element from LazyReexports.
|
||||
JITDylibSP SpeculateJD = nullptr;
|
||||
SymbolStringPtr SpeculateFn;
|
||||
|
||||
auto SpeculateAgain = ES.runSessionLocked([&]() {
|
||||
while (!SpeculateSuggestions.empty()) {
|
||||
auto [JDName, SymbolName] = std::move(SpeculateSuggestions.front());
|
||||
SpeculateSuggestions.pop_front();
|
||||
|
||||
if (auto *JD = ES.getJITDylibByName(JDName)) {
|
||||
SpeculateJD = JD;
|
||||
SpeculateFn = std::move(SymbolName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SpeculateJD) {
|
||||
assert(!LazyReexports.empty() && "LazyReexports map is empty");
|
||||
auto LRItr =
|
||||
std::next(LazyReexports.begin(), rand() % LazyReexports.size());
|
||||
auto &[JD, KeyToFnBodies] = *LRItr;
|
||||
|
||||
assert(!KeyToFnBodies.empty() && "Key to function bodies map empty");
|
||||
auto KeyToFnBodiesItr =
|
||||
std::next(KeyToFnBodies.begin(), rand() % KeyToFnBodies.size());
|
||||
auto &[Key, FnBodies] = *KeyToFnBodiesItr;
|
||||
|
||||
assert(!FnBodies.empty() && "Function bodies list empty");
|
||||
auto FnBodyItr = std::next(FnBodies.begin(), rand() % FnBodies.size());
|
||||
|
||||
SpeculateJD = JITDylibSP(JD);
|
||||
SpeculateFn = std::move(*FnBodyItr);
|
||||
|
||||
FnBodies.erase(FnBodyItr);
|
||||
if (FnBodies.empty()) {
|
||||
KeyToFnBodies.erase(KeyToFnBodiesItr);
|
||||
if (KeyToFnBodies.empty()) {
|
||||
LRItr->first->Release();
|
||||
LazyReexports.erase(LRItr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpeculateTaskActive =
|
||||
!SpeculateSuggestions.empty() || !LazyReexports.empty();
|
||||
return SpeculateTaskActive;
|
||||
});
|
||||
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "Issuing speculative lookup for ( " << SpeculateJD->getName()
|
||||
<< ", " << SpeculateFn << " )...\n";
|
||||
});
|
||||
|
||||
ES.lookup(
|
||||
LookupKind::Static, makeJITDylibSearchOrder(SpeculateJD.get()),
|
||||
{{std::move(SpeculateFn), SymbolLookupFlags::WeaklyReferencedSymbol}},
|
||||
SymbolState::Ready,
|
||||
[](Expected<SymbolMap> Result) { consumeError(Result.takeError()); },
|
||||
NoDependenciesToRegister);
|
||||
|
||||
if (SpeculateAgain)
|
||||
ES.dispatchTask(std::make_unique<SpeculateTask>(WeakThis));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
||||
@@ -15,13 +15,9 @@ namespace orc {
|
||||
|
||||
char Task::ID = 0;
|
||||
char GenericNamedTask::ID = 0;
|
||||
char IdleTask::ID = 0;
|
||||
|
||||
const char *GenericNamedTask::DefaultDescription = "Generic Task";
|
||||
|
||||
void Task::anchor() {}
|
||||
void IdleTask::anchor() {}
|
||||
|
||||
TaskDispatcher::~TaskDispatcher() = default;
|
||||
|
||||
void InPlaceTaskDispatcher::dispatch(std::unique_ptr<Task> T) { T->run(); }
|
||||
@@ -30,15 +26,7 @@ void InPlaceTaskDispatcher::shutdown() {}
|
||||
|
||||
#if LLVM_ENABLE_THREADS
|
||||
void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) {
|
||||
|
||||
enum { Normal, Materialization, Idle } TaskKind;
|
||||
|
||||
if (isa<MaterializationTask>(*T))
|
||||
TaskKind = Materialization;
|
||||
else if (isa<IdleTask>(*T))
|
||||
TaskKind = Idle;
|
||||
else
|
||||
TaskKind = Normal;
|
||||
bool IsMaterializationTask = isa<MaterializationTask>(*T);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> Lock(DispatchMutex);
|
||||
@@ -47,24 +35,24 @@ void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) {
|
||||
if (Shutdown)
|
||||
return;
|
||||
|
||||
if (TaskKind == Materialization) {
|
||||
if (IsMaterializationTask) {
|
||||
|
||||
// If this is a materialization task and there are too many running
|
||||
// already then queue this one up and return early.
|
||||
if (!canRunMaterializationTaskNow())
|
||||
return MaterializationTaskQueue.push_back(std::move(T));
|
||||
if (MaxMaterializationThreads &&
|
||||
NumMaterializationThreads == *MaxMaterializationThreads) {
|
||||
MaterializationTaskQueue.push_back(std::move(T));
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise record that we have a materialization task running.
|
||||
++NumMaterializationThreads;
|
||||
} else if (TaskKind == Idle) {
|
||||
if (!canRunIdleTaskNow())
|
||||
return IdleTaskQueue.push_back(std::move(T));
|
||||
}
|
||||
|
||||
++Outstanding;
|
||||
}
|
||||
|
||||
std::thread([this, T = std::move(T), TaskKind]() mutable {
|
||||
std::thread([this, T = std::move(T), IsMaterializationTask]() mutable {
|
||||
while (true) {
|
||||
|
||||
// Run the task.
|
||||
@@ -79,24 +67,18 @@ void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) {
|
||||
// Check the work queue state and either proceed with the next task or
|
||||
// end this thread.
|
||||
std::lock_guard<std::mutex> Lock(DispatchMutex);
|
||||
|
||||
if (TaskKind == Materialization)
|
||||
--NumMaterializationThreads;
|
||||
--Outstanding;
|
||||
|
||||
if (!MaterializationTaskQueue.empty() && canRunMaterializationTaskNow()) {
|
||||
if (!MaterializationTaskQueue.empty()) {
|
||||
// If there are any materialization tasks running then steal that work.
|
||||
T = std::move(MaterializationTaskQueue.front());
|
||||
MaterializationTaskQueue.pop_front();
|
||||
TaskKind = Materialization;
|
||||
++NumMaterializationThreads;
|
||||
++Outstanding;
|
||||
} else if (!IdleTaskQueue.empty() && canRunIdleTaskNow()) {
|
||||
T = std::move(IdleTaskQueue.front());
|
||||
IdleTaskQueue.pop_front();
|
||||
TaskKind = Idle;
|
||||
++Outstanding;
|
||||
if (!IsMaterializationTask) {
|
||||
++NumMaterializationThreads;
|
||||
IsMaterializationTask = true;
|
||||
}
|
||||
} else {
|
||||
if (IsMaterializationTask)
|
||||
--NumMaterializationThreads;
|
||||
--Outstanding;
|
||||
if (Outstanding == 0)
|
||||
OutstandingCV.notify_all();
|
||||
return;
|
||||
@@ -110,17 +92,6 @@ void DynamicThreadPoolTaskDispatcher::shutdown() {
|
||||
Shutdown = true;
|
||||
OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });
|
||||
}
|
||||
|
||||
bool DynamicThreadPoolTaskDispatcher::canRunMaterializationTaskNow() {
|
||||
return !MaxMaterializationThreads ||
|
||||
(NumMaterializationThreads < *MaxMaterializationThreads);
|
||||
}
|
||||
|
||||
bool DynamicThreadPoolTaskDispatcher::canRunIdleTaskNow() {
|
||||
return !MaxMaterializationThreads ||
|
||||
(Outstanding < *MaxMaterializationThreads);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace orc
|
||||
|
||||
@@ -83,35 +83,13 @@ using namespace llvm::orc;
|
||||
|
||||
static cl::OptionCategory JITLinkCategory("JITLink Options");
|
||||
|
||||
static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
|
||||
cl::desc("input files"),
|
||||
cl::cat(JITLinkCategory));
|
||||
|
||||
static cl::list<bool> LazyLink("lazy",
|
||||
cl::desc("Link the following file lazily"),
|
||||
cl::cat(JITLinkCategory));
|
||||
|
||||
enum class SpeculateKind { None, Simple };
|
||||
|
||||
cl::opt<SpeculateKind> Speculate(
|
||||
"speculate", cl::desc("Choose speculation scheme"),
|
||||
cl::init(SpeculateKind::None),
|
||||
cl::values(clEnumValN(SpeculateKind::None, "none", "No speculation"),
|
||||
clEnumValN(SpeculateKind::Simple, "simple",
|
||||
"Simple speculation")),
|
||||
cl::cat(JITLinkCategory));
|
||||
|
||||
cl::opt<std::string> SpeculateOrder(
|
||||
"speculate-order",
|
||||
cl::desc("A CSV file containing (JITDylib, Function) pairs to"
|
||||
"speculatively look up"),
|
||||
cl::cat(JITLinkCategory));
|
||||
|
||||
cl::opt<std::string> RecordLazyExecs(
|
||||
"record-lazy-execs",
|
||||
cl::desc("Write lazy-function executions to a CSV file as (JITDylib, "
|
||||
"function) pairs"),
|
||||
cl::cat(JITLinkCategory));
|
||||
static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
|
||||
cl::desc("input files"),
|
||||
cl::cat(JITLinkCategory));
|
||||
|
||||
static cl::opt<size_t> MaterializationThreads(
|
||||
"num-threads", cl::desc("Number of materialization threads to use"),
|
||||
@@ -981,50 +959,17 @@ public:
|
||||
};
|
||||
|
||||
Expected<std::unique_ptr<Session::LazyLinkingSupport>>
|
||||
createLazyLinkingSupport(Session &S) {
|
||||
auto RSMgr = JITLinkRedirectableSymbolManager::Create(S.ObjLayer);
|
||||
createLazyLinkingSupport(ObjectLinkingLayer &OLL, JITDylib &PlatformJD) {
|
||||
auto RSMgr = JITLinkRedirectableSymbolManager::Create(OLL);
|
||||
if (!RSMgr)
|
||||
return RSMgr.takeError();
|
||||
|
||||
std::shared_ptr<SimpleLazyReexportsSpeculator> Speculator;
|
||||
switch (Speculate) {
|
||||
case SpeculateKind::None:
|
||||
break;
|
||||
case SpeculateKind::Simple:
|
||||
SimpleLazyReexportsSpeculator::RecordExecutionFunction RecordExecs;
|
||||
|
||||
if (!RecordLazyExecs.empty())
|
||||
RecordExecs = [&S](const LazyReexportsManager::CallThroughInfo &CTI) {
|
||||
S.LazyFnExecOrder.push_back({CTI.JD->getName(), CTI.BodyName});
|
||||
};
|
||||
|
||||
Speculator =
|
||||
SimpleLazyReexportsSpeculator::Create(S.ES, std::move(RecordExecs));
|
||||
break;
|
||||
}
|
||||
|
||||
auto LRMgr = createJITLinkLazyReexportsManager(
|
||||
S.ObjLayer, **RSMgr, *S.PlatformJD, Speculator.get());
|
||||
auto LRMgr = createJITLinkLazyReexportsManager(OLL, **RSMgr, PlatformJD);
|
||||
if (!LRMgr)
|
||||
return LRMgr.takeError();
|
||||
|
||||
return std::make_unique<Session::LazyLinkingSupport>(
|
||||
std::move(*RSMgr), std::move(Speculator), std::move(*LRMgr), S.ObjLayer);
|
||||
}
|
||||
|
||||
static Error writeLazyExecOrder(Session &S) {
|
||||
if (RecordLazyExecs.empty())
|
||||
return Error::success();
|
||||
|
||||
std::error_code EC;
|
||||
raw_fd_ostream ExecOrderOut(RecordLazyExecs, EC);
|
||||
if (EC)
|
||||
return createFileError(RecordLazyExecs, EC);
|
||||
|
||||
for (auto &[JDName, FunctionName] : S.LazyFnExecOrder)
|
||||
ExecOrderOut << JDName << ", " << FunctionName << "\n";
|
||||
|
||||
return Error::success();
|
||||
return std::make_unique<Session::LazyLinkingSupport>(std::move(*RSMgr),
|
||||
std::move(*LRMgr), OLL);
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
|
||||
@@ -1072,7 +1017,8 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
|
||||
S->Features = std::move(Features);
|
||||
|
||||
if (lazyLinkingRequested()) {
|
||||
if (auto LazyLinking = createLazyLinkingSupport(*S))
|
||||
if (auto LazyLinking =
|
||||
createLazyLinkingSupport(S->ObjLayer, *S->PlatformJD))
|
||||
S->LazyLinking = std::move(*LazyLinking);
|
||||
else
|
||||
return LazyLinking.takeError();
|
||||
@@ -1082,9 +1028,6 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
|
||||
}
|
||||
|
||||
Session::~Session() {
|
||||
if (auto Err = writeLazyExecOrder(*this))
|
||||
ES.reportError(std::move(Err));
|
||||
|
||||
if (auto Err = ES.endSession())
|
||||
ES.reportError(std::move(Err));
|
||||
}
|
||||
@@ -1759,23 +1702,6 @@ static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
|
||||
return make_error<StringError>(
|
||||
"Lazy linking cannot be used with -harness mode",
|
||||
inconvertibleErrorCode());
|
||||
} else if (Speculate != SpeculateKind::None) {
|
||||
errs() << "Warning: -speculate ignored as there are no -lazy inputs\n";
|
||||
Speculate = SpeculateKind::None;
|
||||
}
|
||||
|
||||
if (Speculate == SpeculateKind::None) {
|
||||
if (!SpeculateOrder.empty()) {
|
||||
errs() << "Warning: -speculate-order ignored because speculation is "
|
||||
"disabled\n";
|
||||
SpeculateOrder = "";
|
||||
}
|
||||
|
||||
if (!RecordLazyExecs.empty()) {
|
||||
errs() << "Warning: -record-lazy-execs ignored because speculation is "
|
||||
"disabled\n";
|
||||
RecordLazyExecs = "";
|
||||
}
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
@@ -2341,59 +2267,6 @@ static Error addLibraries(Session &S,
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error addSpeculationOrder(Session &S) {
|
||||
|
||||
if (SpeculateOrder.empty())
|
||||
return Error::success();
|
||||
|
||||
assert(S.LazyLinking && "SpeculateOrder set, but lazy linking not enabled");
|
||||
assert(S.LazyLinking->Speculator && "SpeculatoOrder set, but no speculator");
|
||||
|
||||
auto SpecOrderBuffer = getFile(SpeculateOrder);
|
||||
if (!SpecOrderBuffer)
|
||||
return SpecOrderBuffer.takeError();
|
||||
|
||||
StringRef LineStream((*SpecOrderBuffer)->getBuffer());
|
||||
std::vector<std::pair<std::string, SymbolStringPtr>> SpecOrder;
|
||||
|
||||
size_t LineNumber = 0;
|
||||
while (!LineStream.empty()) {
|
||||
++LineNumber;
|
||||
|
||||
auto MakeSpecOrderErr = [&](StringRef Reason) {
|
||||
return make_error<StringError>("Error in speculation order file \"" +
|
||||
SpeculateOrder + "\" on line " +
|
||||
Twine(LineNumber) + ": " + Reason,
|
||||
inconvertibleErrorCode());
|
||||
};
|
||||
|
||||
StringRef CurLine;
|
||||
std::tie(CurLine, LineStream) = LineStream.split('\n');
|
||||
CurLine = CurLine.trim();
|
||||
if (CurLine.empty())
|
||||
continue;
|
||||
|
||||
auto [JDName, FuncName] = CurLine.split(',');
|
||||
|
||||
if (FuncName.empty())
|
||||
return MakeSpecOrderErr("missing ',' separator");
|
||||
|
||||
JDName = JDName.trim();
|
||||
if (JDName.empty())
|
||||
return MakeSpecOrderErr("no value for column 1 (JIT Dylib name)");
|
||||
|
||||
FuncName = FuncName.trim();
|
||||
if (FuncName.empty())
|
||||
return MakeSpecOrderErr("no value for column 2 (function name)");
|
||||
|
||||
SpecOrder.push_back({JDName.str(), S.ES.intern(FuncName)});
|
||||
}
|
||||
|
||||
S.LazyLinking->Speculator->addSpeculationSuggestions(std::move(SpecOrder));
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error addSessionInputs(Session &S) {
|
||||
std::map<unsigned, JITDylib *> IdxToJD;
|
||||
DenseSet<unsigned> LazyLinkIdxs;
|
||||
@@ -2426,9 +2299,6 @@ static Error addSessionInputs(Session &S) {
|
||||
if (auto Err = addLibraries(S, IdxToJD, LazyLinkIdxs))
|
||||
return Err;
|
||||
|
||||
if (auto Err = addSpeculationOrder(S))
|
||||
return Err;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,17 +33,13 @@ namespace llvm {
|
||||
struct Session {
|
||||
|
||||
struct LazyLinkingSupport {
|
||||
LazyLinkingSupport(
|
||||
std::unique_ptr<orc::RedirectableSymbolManager> RSMgr,
|
||||
std::shared_ptr<orc::SimpleLazyReexportsSpeculator> Speculator,
|
||||
std::unique_ptr<orc::LazyReexportsManager> LRMgr,
|
||||
orc::ObjectLinkingLayer &ObjLinkingLayer)
|
||||
: RSMgr(std::move(RSMgr)), Speculator(std::move(Speculator)),
|
||||
LRMgr(std::move(LRMgr)),
|
||||
LazyLinkingSupport(std::unique_ptr<orc::RedirectableSymbolManager> RSMgr,
|
||||
std::unique_ptr<orc::LazyReexportsManager> LRMgr,
|
||||
orc::ObjectLinkingLayer &ObjLinkingLayer)
|
||||
: RSMgr(std::move(RSMgr)), LRMgr(std::move(LRMgr)),
|
||||
LazyObjLinkingLayer(ObjLinkingLayer, *this->LRMgr) {}
|
||||
|
||||
std::unique_ptr<orc::RedirectableSymbolManager> RSMgr;
|
||||
std::shared_ptr<orc::SimpleLazyReexportsSpeculator> Speculator;
|
||||
std::unique_ptr<orc::LazyReexportsManager> LRMgr;
|
||||
orc::LazyObjectLinkingLayer LazyObjLinkingLayer;
|
||||
};
|
||||
@@ -56,7 +52,6 @@ struct Session {
|
||||
std::unique_ptr<LazyLinkingSupport> LazyLinking;
|
||||
orc::JITDylibSearchOrder JDSearchOrder;
|
||||
SubtargetFeatures Features;
|
||||
std::vector<std::pair<std::string, orc::SymbolStringPtr>> LazyFnExecOrder;
|
||||
|
||||
~Session();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user