aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp')
-rw-r--r--llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp146
1 files changed, 100 insertions, 46 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp b/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
index c2e7baabb994..d099a251232e 100644
--- a/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
@@ -8,11 +8,10 @@
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Support/Process.h"
-#include <limits>
-
using namespace llvm::jitlink;
namespace llvm {
@@ -33,7 +32,8 @@ public:
std::swap(AI.Segments, Segs);
std::swap(AI.Actions, G.allocActions());
- Parent.Mapper->initialize(AI, [&](Expected<ExecutorAddr> Result) {
+ Parent.Mapper->initialize(AI, [OnFinalize = std::move(OnFinalize)](
+ Expected<ExecutorAddr> Result) mutable {
if (!Result) {
OnFinalize(Result.takeError());
return;
@@ -55,8 +55,9 @@ private:
};
MapperJITLinkMemoryManager::MapperJITLinkMemoryManager(
- std::unique_ptr<MemoryMapper> Mapper)
- : Mapper(std::move(Mapper)) {}
+ size_t ReservationGranularity, std::unique_ptr<MemoryMapper> Mapper)
+ : ReservationUnits(ReservationGranularity), AvailableMemory(AMAllocator),
+ Mapper(std::move(Mapper)) {}
void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
OnAllocatedFunction OnAllocated) {
@@ -69,55 +70,78 @@ void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
return;
}
- // Check if total size fits in address space
- 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;
- }
+ auto TotalSize = SegsSizes->total();
+
+ auto CompleteAllocation = [this, &G, BL = std::move(BL),
+ OnAllocated = std::move(OnAllocated)](
+ Expected<ExecutorAddrRange> Result) mutable {
+ if (!Result) {
+ Mutex.unlock();
+ 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;
- 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 TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
- auto NextSegAddr = Result->Start;
+ Seg.Addr = NextSegAddr;
+ Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
- std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
+ NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
- for (auto &KV : BL.segments()) {
- auto &AG = KV.first;
- auto &Seg = KV.second;
+ MemoryMapper::AllocInfo::SegInfo SI;
+ SI.Offset = Seg.Addr - Result->Start;
+ SI.ContentSize = Seg.ContentSize;
+ SI.ZeroFillSize = Seg.ZeroFillSize;
+ SI.AG = AG;
+ SI.WorkingMem = Seg.WorkingMem;
- auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
+ SegInfos.push_back(SI);
+ }
- Seg.Addr = NextSegAddr;
- Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
+ UsedMemory.insert({Result->Start, NextSegAddr - Result->Start});
- NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
+ if (NextSegAddr < Result->End) {
+ // Save the remaining memory for reuse in next allocation(s)
+ AvailableMemory.insert(NextSegAddr, Result->End - 1, true);
+ }
+ Mutex.unlock();
- 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;
+ if (auto Err = BL.apply()) {
+ OnAllocated(std::move(Err));
+ return;
+ }
- SegInfos.push_back(SI);
- }
+ OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
+ std::move(SegInfos)));
+ };
- if (auto Err = BL.apply()) {
- OnAllocated(std::move(Err));
- return;
- }
+ Mutex.lock();
- OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
- std::move(SegInfos)));
- });
+ // find an already reserved range that is large enough
+ ExecutorAddrRange SelectedRange{};
+
+ for (AvailableMemoryMap::iterator It = AvailableMemory.begin();
+ It != AvailableMemory.end(); It++) {
+ if (It.stop() - It.start() + 1 >= TotalSize) {
+ SelectedRange = ExecutorAddrRange(It.start(), It.stop() + 1);
+ It.erase();
+ break;
+ }
+ }
+
+ if (SelectedRange.empty()) { // no already reserved range was found
+ auto TotalAllocation = alignTo(TotalSize, ReservationUnits);
+ Mapper->reserve(TotalAllocation, std::move(CompleteAllocation));
+ } else {
+ CompleteAllocation(SelectedRange);
+ }
}
void MapperJITLinkMemoryManager::deallocate(
@@ -125,10 +149,40 @@ void MapperJITLinkMemoryManager::deallocate(
std::vector<ExecutorAddr> Bases;
Bases.reserve(Allocs.size());
for (auto &FA : Allocs) {
- Bases.push_back(FA.getAddress());
- FA.release();
+ ExecutorAddr Addr = FA.getAddress();
+ Bases.push_back(Addr);
}
- Mapper->release(Bases, std::move(OnDeallocated));
+
+ Mapper->deinitialize(Bases, [this, Allocs = std::move(Allocs),
+ OnDeallocated = std::move(OnDeallocated)](
+ llvm::Error Err) mutable {
+ // TODO: How should we treat memory that we fail to deinitialize?
+ // We're currently bailing out and treating it as "burned" -- should we
+ // require that a failure to deinitialize still reset the memory so that
+ // we can reclaim it?
+ if (Err) {
+ for (auto &FA : Allocs)
+ FA.release();
+ OnDeallocated(std::move(Err));
+ return;
+ }
+
+ {
+ std::lock_guard<std::mutex> Lock(Mutex);
+
+ for (auto &FA : Allocs) {
+ ExecutorAddr Addr = FA.getAddress();
+ ExecutorAddrDiff Size = UsedMemory[Addr];
+
+ UsedMemory.erase(Addr);
+ AvailableMemory.insert(Addr, Addr + Size - 1, true);
+
+ FA.release();
+ }
+ }
+
+ OnDeallocated(Error::success());
+ });
}
} // end namespace orc