xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp (revision 1f4d91ecb8529678a3d3919d7523743bd21942ca)
14fcf8434SAnubhab Ghosh //=== MapperJITLinkMemoryManager.cpp - Memory management with MemoryMapper ===//
24fcf8434SAnubhab Ghosh //
34fcf8434SAnubhab Ghosh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44fcf8434SAnubhab Ghosh // See https://llvm.org/LICENSE.txt for license information.
54fcf8434SAnubhab Ghosh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64fcf8434SAnubhab Ghosh //
74fcf8434SAnubhab Ghosh //===----------------------------------------------------------------------===//
84fcf8434SAnubhab Ghosh 
94fcf8434SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
104fcf8434SAnubhab Ghosh 
114fcf8434SAnubhab Ghosh #include "llvm/ExecutionEngine/JITLink/JITLink.h"
124fcf8434SAnubhab Ghosh #include "llvm/Support/Process.h"
134fcf8434SAnubhab Ghosh 
144fcf8434SAnubhab Ghosh using namespace llvm::jitlink;
154fcf8434SAnubhab Ghosh 
164fcf8434SAnubhab Ghosh namespace llvm {
174fcf8434SAnubhab Ghosh namespace orc {
184fcf8434SAnubhab Ghosh 
194fcf8434SAnubhab Ghosh class MapperJITLinkMemoryManager::InFlightAlloc
204fcf8434SAnubhab Ghosh     : public JITLinkMemoryManager::InFlightAlloc {
214fcf8434SAnubhab Ghosh public:
224fcf8434SAnubhab Ghosh   InFlightAlloc(MapperJITLinkMemoryManager &Parent, LinkGraph &G,
234fcf8434SAnubhab Ghosh                 ExecutorAddr AllocAddr,
244fcf8434SAnubhab Ghosh                 std::vector<MemoryMapper::AllocInfo::SegInfo> Segs)
254fcf8434SAnubhab Ghosh       : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
264fcf8434SAnubhab Ghosh 
274fcf8434SAnubhab Ghosh   void finalize(OnFinalizedFunction OnFinalize) override {
284fcf8434SAnubhab Ghosh     MemoryMapper::AllocInfo AI;
294fcf8434SAnubhab Ghosh     AI.MappingBase = AllocAddr;
304fcf8434SAnubhab Ghosh 
314fcf8434SAnubhab Ghosh     std::swap(AI.Segments, Segs);
324fcf8434SAnubhab Ghosh     std::swap(AI.Actions, G.allocActions());
334fcf8434SAnubhab Ghosh 
345df428eaSAnubhab Ghosh     Parent.Mapper->initialize(AI, [OnFinalize = std::move(OnFinalize)](
355df428eaSAnubhab Ghosh                                       Expected<ExecutorAddr> Result) mutable {
364fcf8434SAnubhab Ghosh       if (!Result) {
374fcf8434SAnubhab Ghosh         OnFinalize(Result.takeError());
384fcf8434SAnubhab Ghosh         return;
394fcf8434SAnubhab Ghosh       }
404fcf8434SAnubhab Ghosh 
414fcf8434SAnubhab Ghosh       OnFinalize(FinalizedAlloc(*Result));
424fcf8434SAnubhab Ghosh     });
434fcf8434SAnubhab Ghosh   }
444fcf8434SAnubhab Ghosh 
454fcf8434SAnubhab Ghosh   void abandon(OnAbandonedFunction OnFinalize) override {
464fcf8434SAnubhab Ghosh     Parent.Mapper->release({AllocAddr}, std::move(OnFinalize));
474fcf8434SAnubhab Ghosh   }
484fcf8434SAnubhab Ghosh 
494fcf8434SAnubhab Ghosh private:
504fcf8434SAnubhab Ghosh   MapperJITLinkMemoryManager &Parent;
514fcf8434SAnubhab Ghosh   LinkGraph &G;
524fcf8434SAnubhab Ghosh   ExecutorAddr AllocAddr;
534fcf8434SAnubhab Ghosh   std::vector<MemoryMapper::AllocInfo::SegInfo> Segs;
544fcf8434SAnubhab Ghosh };
554fcf8434SAnubhab Ghosh 
564fcf8434SAnubhab Ghosh MapperJITLinkMemoryManager::MapperJITLinkMemoryManager(
571eee6de8SAnubhab Ghosh     size_t ReservationGranularity, std::unique_ptr<MemoryMapper> Mapper)
5823d0e71fSAnubhab Ghosh     : ReservationUnits(ReservationGranularity), AvailableMemory(AMAllocator),
5923d0e71fSAnubhab Ghosh       Mapper(std::move(Mapper)) {}
604fcf8434SAnubhab Ghosh 
614fcf8434SAnubhab Ghosh void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
624fcf8434SAnubhab Ghosh                                           OnAllocatedFunction OnAllocated) {
634fcf8434SAnubhab Ghosh   BasicLayout BL(G);
644fcf8434SAnubhab Ghosh 
654fcf8434SAnubhab Ghosh   // find required address space
664fcf8434SAnubhab Ghosh   auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(Mapper->getPageSize());
674fcf8434SAnubhab Ghosh   if (!SegsSizes) {
684fcf8434SAnubhab Ghosh     OnAllocated(SegsSizes.takeError());
694fcf8434SAnubhab Ghosh     return;
704fcf8434SAnubhab Ghosh   }
714fcf8434SAnubhab Ghosh 
721eee6de8SAnubhab Ghosh   auto TotalSize = SegsSizes->total();
731eee6de8SAnubhab Ghosh 
741eee6de8SAnubhab Ghosh   auto CompleteAllocation = [this, &G, BL = std::move(BL),
751eee6de8SAnubhab Ghosh                              OnAllocated = std::move(OnAllocated)](
764fcf8434SAnubhab Ghosh                                 Expected<ExecutorAddrRange> Result) mutable {
774fcf8434SAnubhab Ghosh     if (!Result) {
781eee6de8SAnubhab Ghosh       Mutex.unlock();
794fcf8434SAnubhab Ghosh       return OnAllocated(Result.takeError());
804fcf8434SAnubhab Ghosh     }
814fcf8434SAnubhab Ghosh 
824fcf8434SAnubhab Ghosh     auto NextSegAddr = Result->Start;
834fcf8434SAnubhab Ghosh 
844fcf8434SAnubhab Ghosh     std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
854fcf8434SAnubhab Ghosh 
864fcf8434SAnubhab Ghosh     for (auto &KV : BL.segments()) {
874fcf8434SAnubhab Ghosh       auto &AG = KV.first;
884fcf8434SAnubhab Ghosh       auto &Seg = KV.second;
894fcf8434SAnubhab Ghosh 
904fcf8434SAnubhab Ghosh       auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
914fcf8434SAnubhab Ghosh 
924fcf8434SAnubhab Ghosh       Seg.Addr = NextSegAddr;
934fcf8434SAnubhab Ghosh       Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
944fcf8434SAnubhab Ghosh 
954fcf8434SAnubhab Ghosh       NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
964fcf8434SAnubhab Ghosh 
974fcf8434SAnubhab Ghosh       MemoryMapper::AllocInfo::SegInfo SI;
984fcf8434SAnubhab Ghosh       SI.Offset = Seg.Addr - Result->Start;
994fcf8434SAnubhab Ghosh       SI.ContentSize = Seg.ContentSize;
1004fcf8434SAnubhab Ghosh       SI.ZeroFillSize = Seg.ZeroFillSize;
101*d3d9f7caSLang Hames       SI.AG = AG;
1024fcf8434SAnubhab Ghosh       SI.WorkingMem = Seg.WorkingMem;
1034fcf8434SAnubhab Ghosh 
1044fcf8434SAnubhab Ghosh       SegInfos.push_back(SI);
1054fcf8434SAnubhab Ghosh     }
1064fcf8434SAnubhab Ghosh 
1071eee6de8SAnubhab Ghosh     UsedMemory.insert({Result->Start, NextSegAddr - Result->Start});
1081eee6de8SAnubhab Ghosh 
1091eee6de8SAnubhab Ghosh     if (NextSegAddr < Result->End) {
1101eee6de8SAnubhab Ghosh       // Save the remaining memory for reuse in next allocation(s)
11123d0e71fSAnubhab Ghosh       AvailableMemory.insert(NextSegAddr, Result->End - 1, true);
1121eee6de8SAnubhab Ghosh     }
1131eee6de8SAnubhab Ghosh     Mutex.unlock();
1141eee6de8SAnubhab Ghosh 
1154fcf8434SAnubhab Ghosh     if (auto Err = BL.apply()) {
1164fcf8434SAnubhab Ghosh       OnAllocated(std::move(Err));
1174fcf8434SAnubhab Ghosh       return;
1184fcf8434SAnubhab Ghosh     }
1194fcf8434SAnubhab Ghosh 
1204fcf8434SAnubhab Ghosh     OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
1214fcf8434SAnubhab Ghosh                                                 std::move(SegInfos)));
1221eee6de8SAnubhab Ghosh   };
1231eee6de8SAnubhab Ghosh 
12423d0e71fSAnubhab Ghosh   Mutex.lock();
12523d0e71fSAnubhab Ghosh 
12623d0e71fSAnubhab Ghosh   // find an already reserved range that is large enough
12723d0e71fSAnubhab Ghosh   ExecutorAddrRange SelectedRange{};
12823d0e71fSAnubhab Ghosh 
12923d0e71fSAnubhab Ghosh   for (AvailableMemoryMap::iterator It = AvailableMemory.begin();
13023d0e71fSAnubhab Ghosh        It != AvailableMemory.end(); It++) {
13123d0e71fSAnubhab Ghosh     if (It.stop() - It.start() + 1 >= TotalSize) {
13223d0e71fSAnubhab Ghosh       SelectedRange = ExecutorAddrRange(It.start(), It.stop() + 1);
13323d0e71fSAnubhab Ghosh       It.erase();
13423d0e71fSAnubhab Ghosh       break;
13523d0e71fSAnubhab Ghosh     }
13623d0e71fSAnubhab Ghosh   }
13723d0e71fSAnubhab Ghosh 
1381eee6de8SAnubhab Ghosh   if (SelectedRange.empty()) { // no already reserved range was found
1391eee6de8SAnubhab Ghosh     auto TotalAllocation = alignTo(TotalSize, ReservationUnits);
1401eee6de8SAnubhab Ghosh     Mapper->reserve(TotalAllocation, std::move(CompleteAllocation));
1411eee6de8SAnubhab Ghosh   } else {
1421eee6de8SAnubhab Ghosh     CompleteAllocation(SelectedRange);
1431eee6de8SAnubhab Ghosh   }
1444fcf8434SAnubhab Ghosh }
1454fcf8434SAnubhab Ghosh 
1464fcf8434SAnubhab Ghosh void MapperJITLinkMemoryManager::deallocate(
1474fcf8434SAnubhab Ghosh     std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
148a31af321SAnubhab Ghosh   std::vector<ExecutorAddr> Bases;
149a31af321SAnubhab Ghosh   Bases.reserve(Allocs.size());
150a31af321SAnubhab Ghosh   for (auto &FA : Allocs) {
151a31af321SAnubhab Ghosh     ExecutorAddr Addr = FA.getAddress();
152a31af321SAnubhab Ghosh     Bases.push_back(Addr);
153a31af321SAnubhab Ghosh   }
154a31af321SAnubhab Ghosh 
155a31af321SAnubhab Ghosh   Mapper->deinitialize(Bases, [this, Allocs = std::move(Allocs),
156a31af321SAnubhab Ghosh                                OnDeallocated = std::move(OnDeallocated)](
157a31af321SAnubhab Ghosh                                   llvm::Error Err) mutable {
15847e9e588SLang Hames     // TODO: How should we treat memory that we fail to deinitialize?
15947e9e588SLang Hames     // We're currently bailing out and treating it as "burned" -- should we
16047e9e588SLang Hames     // require that a failure to deinitialize still reset the memory so that
16147e9e588SLang Hames     // we can reclaim it?
16247e9e588SLang Hames     if (Err) {
16347e9e588SLang Hames       for (auto &FA : Allocs)
16447e9e588SLang Hames         FA.release();
165a31af321SAnubhab Ghosh       OnDeallocated(std::move(Err));
16647e9e588SLang Hames       return;
16747e9e588SLang Hames     }
168a31af321SAnubhab Ghosh 
169a31af321SAnubhab Ghosh     {
1701eee6de8SAnubhab Ghosh       std::lock_guard<std::mutex> Lock(Mutex);
1711eee6de8SAnubhab Ghosh 
1724fcf8434SAnubhab Ghosh       for (auto &FA : Allocs) {
1731eee6de8SAnubhab Ghosh         ExecutorAddr Addr = FA.getAddress();
1741eee6de8SAnubhab Ghosh         ExecutorAddrDiff Size = UsedMemory[Addr];
175143555b2SAnubhab Ghosh 
176a31af321SAnubhab Ghosh         UsedMemory.erase(Addr);
17723d0e71fSAnubhab Ghosh         AvailableMemory.insert(Addr, Addr + Size - 1, true);
178a31af321SAnubhab Ghosh 
17981801051SAnubhab Ghosh         FA.release();
18081801051SAnubhab Ghosh       }
181a31af321SAnubhab Ghosh     }
182a31af321SAnubhab Ghosh 
1831eee6de8SAnubhab Ghosh     OnDeallocated(Error::success());
184a31af321SAnubhab Ghosh   });
1854fcf8434SAnubhab Ghosh }
1864fcf8434SAnubhab Ghosh 
1874fcf8434SAnubhab Ghosh } // end namespace orc
1884fcf8434SAnubhab Ghosh } // end namespace llvm
189