#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Support/Process.h"
#include <limits>
using namespace llvm::jitlink;
namespace llvm {
namespace orc {
class MapperJITLinkMemoryManager::InFlightAlloc
: public JITLinkMemoryManager::InFlightAlloc {
public:
InFlightAlloc(MapperJITLinkMemoryManager &Parent, LinkGraph &G,
ExecutorAddr AllocAddr,
std::vector<MemoryMapper::AllocInfo::SegInfo> Segs)
: Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
void finalize(OnFinalizedFunction OnFinalize) override {
MemoryMapper::AllocInfo AI;
AI.MappingBase = AllocAddr;
std::swap(AI.Segments, Segs);
std::swap(AI.Actions, G.allocActions());
Parent.Mapper->initialize(AI, [&](Expected<ExecutorAddr> Result) {
if (!Result) {
OnFinalize(Result.takeError());
return;
}
OnFinalize(FinalizedAlloc(*Result));
});
}
void abandon(OnAbandonedFunction OnFinalize) override {
Parent.Mapper->release({AllocAddr}, std::move(OnFinalize));
}
private:
MapperJITLinkMemoryManager &Parent;
LinkGraph &G;
ExecutorAddr AllocAddr;
std::vector<MemoryMapper::AllocInfo::SegInfo> Segs;
};
MapperJITLinkMemoryManager::MapperJITLinkMemoryManager(
std::unique_ptr<MemoryMapper> Mapper)
: Mapper(std::move(Mapper)) {}
void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
OnAllocatedFunction OnAllocated) {
BasicLayout BL(G);
auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(Mapper->getPageSize());
if (!SegsSizes) {
OnAllocated(SegsSizes.takeError());
return;
}
if (SegsSizes->total() > std::numeric_limits<size_t>::max()) {
OnAllocated(make_error<JITLinkError>(
formatv("Total requested size {:x} for graph {} exceeds address space",
SegsSizes->total(), G.getName())));
return;
}
Mapper->reserve(
SegsSizes->total(),
[this, &G, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
Expected<ExecutorAddrRange> Result) mutable {
if (!Result) {
return OnAllocated(Result.takeError());
}
auto NextSegAddr = Result->Start;
std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
for (auto &KV : BL.segments()) {
auto &AG = KV.first;
auto &Seg = KV.second;
auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
Seg.Addr = NextSegAddr;
Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
MemoryMapper::AllocInfo::SegInfo SI;
SI.Offset = Seg.Addr - Result->Start;
SI.ContentSize = Seg.ContentSize;
SI.ZeroFillSize = Seg.ZeroFillSize;
SI.Prot = (toSysMemoryProtectionFlags(AG.getMemProt()));
SI.WorkingMem = Seg.WorkingMem;
SegInfos.push_back(SI);
}
if (auto Err = BL.apply()) {
OnAllocated(std::move(Err));
return;
}
OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
std::move(SegInfos)));
});
}
void MapperJITLinkMemoryManager::deallocate(
std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
std::vector<ExecutorAddr> Bases;
Bases.reserve(Allocs.size());
for (auto &FA : Allocs) {
Bases.push_back(FA.getAddress());
FA.release();
}
Mapper->release(Bases, std::move(OnDeallocated));
}
} }