1*4fcf8434SAnubhab Ghosh //=== MapperJITLinkMemoryManager.cpp - Memory management with MemoryMapper ===//
2*4fcf8434SAnubhab Ghosh //
3*4fcf8434SAnubhab Ghosh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4fcf8434SAnubhab Ghosh // See https://llvm.org/LICENSE.txt for license information.
5*4fcf8434SAnubhab Ghosh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4fcf8434SAnubhab Ghosh //
7*4fcf8434SAnubhab Ghosh //===----------------------------------------------------------------------===//
8*4fcf8434SAnubhab Ghosh 
9*4fcf8434SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
10*4fcf8434SAnubhab Ghosh 
11*4fcf8434SAnubhab Ghosh #include "llvm/ExecutionEngine/JITLink/JITLink.h"
12*4fcf8434SAnubhab Ghosh #include "llvm/Support/Process.h"
13*4fcf8434SAnubhab Ghosh 
14*4fcf8434SAnubhab Ghosh #include <limits>
15*4fcf8434SAnubhab Ghosh 
16*4fcf8434SAnubhab Ghosh using namespace llvm::jitlink;
17*4fcf8434SAnubhab Ghosh 
18*4fcf8434SAnubhab Ghosh namespace llvm {
19*4fcf8434SAnubhab Ghosh namespace orc {
20*4fcf8434SAnubhab Ghosh 
21*4fcf8434SAnubhab Ghosh class MapperJITLinkMemoryManager::InFlightAlloc
22*4fcf8434SAnubhab Ghosh     : public JITLinkMemoryManager::InFlightAlloc {
23*4fcf8434SAnubhab Ghosh public:
InFlightAlloc(MapperJITLinkMemoryManager & Parent,LinkGraph & G,ExecutorAddr AllocAddr,std::vector<MemoryMapper::AllocInfo::SegInfo> Segs)24*4fcf8434SAnubhab Ghosh   InFlightAlloc(MapperJITLinkMemoryManager &Parent, LinkGraph &G,
25*4fcf8434SAnubhab Ghosh                 ExecutorAddr AllocAddr,
26*4fcf8434SAnubhab Ghosh                 std::vector<MemoryMapper::AllocInfo::SegInfo> Segs)
27*4fcf8434SAnubhab Ghosh       : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
28*4fcf8434SAnubhab Ghosh 
finalize(OnFinalizedFunction OnFinalize)29*4fcf8434SAnubhab Ghosh   void finalize(OnFinalizedFunction OnFinalize) override {
30*4fcf8434SAnubhab Ghosh     MemoryMapper::AllocInfo AI;
31*4fcf8434SAnubhab Ghosh     AI.MappingBase = AllocAddr;
32*4fcf8434SAnubhab Ghosh 
33*4fcf8434SAnubhab Ghosh     std::swap(AI.Segments, Segs);
34*4fcf8434SAnubhab Ghosh     std::swap(AI.Actions, G.allocActions());
35*4fcf8434SAnubhab Ghosh 
36*4fcf8434SAnubhab Ghosh     Parent.Mapper->initialize(AI, [&](Expected<ExecutorAddr> Result) {
37*4fcf8434SAnubhab Ghosh       if (!Result) {
38*4fcf8434SAnubhab Ghosh         OnFinalize(Result.takeError());
39*4fcf8434SAnubhab Ghosh         return;
40*4fcf8434SAnubhab Ghosh       }
41*4fcf8434SAnubhab Ghosh 
42*4fcf8434SAnubhab Ghosh       OnFinalize(FinalizedAlloc(*Result));
43*4fcf8434SAnubhab Ghosh     });
44*4fcf8434SAnubhab Ghosh   }
45*4fcf8434SAnubhab Ghosh 
abandon(OnAbandonedFunction OnFinalize)46*4fcf8434SAnubhab Ghosh   void abandon(OnAbandonedFunction OnFinalize) override {
47*4fcf8434SAnubhab Ghosh     Parent.Mapper->release({AllocAddr}, std::move(OnFinalize));
48*4fcf8434SAnubhab Ghosh   }
49*4fcf8434SAnubhab Ghosh 
50*4fcf8434SAnubhab Ghosh private:
51*4fcf8434SAnubhab Ghosh   MapperJITLinkMemoryManager &Parent;
52*4fcf8434SAnubhab Ghosh   LinkGraph &G;
53*4fcf8434SAnubhab Ghosh   ExecutorAddr AllocAddr;
54*4fcf8434SAnubhab Ghosh   std::vector<MemoryMapper::AllocInfo::SegInfo> Segs;
55*4fcf8434SAnubhab Ghosh };
56*4fcf8434SAnubhab Ghosh 
MapperJITLinkMemoryManager(std::unique_ptr<MemoryMapper> Mapper)57*4fcf8434SAnubhab Ghosh MapperJITLinkMemoryManager::MapperJITLinkMemoryManager(
58*4fcf8434SAnubhab Ghosh     std::unique_ptr<MemoryMapper> Mapper)
59*4fcf8434SAnubhab Ghosh     : Mapper(std::move(Mapper)) {}
60*4fcf8434SAnubhab Ghosh 
allocate(const JITLinkDylib * JD,LinkGraph & G,OnAllocatedFunction OnAllocated)61*4fcf8434SAnubhab Ghosh void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
62*4fcf8434SAnubhab Ghosh                                           OnAllocatedFunction OnAllocated) {
63*4fcf8434SAnubhab Ghosh   BasicLayout BL(G);
64*4fcf8434SAnubhab Ghosh 
65*4fcf8434SAnubhab Ghosh   // find required address space
66*4fcf8434SAnubhab Ghosh   auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(Mapper->getPageSize());
67*4fcf8434SAnubhab Ghosh   if (!SegsSizes) {
68*4fcf8434SAnubhab Ghosh     OnAllocated(SegsSizes.takeError());
69*4fcf8434SAnubhab Ghosh     return;
70*4fcf8434SAnubhab Ghosh   }
71*4fcf8434SAnubhab Ghosh 
72*4fcf8434SAnubhab Ghosh   // Check if total size fits in address space
73*4fcf8434SAnubhab Ghosh   if (SegsSizes->total() > std::numeric_limits<size_t>::max()) {
74*4fcf8434SAnubhab Ghosh     OnAllocated(make_error<JITLinkError>(
75*4fcf8434SAnubhab Ghosh         formatv("Total requested size {:x} for graph {} exceeds address space",
76*4fcf8434SAnubhab Ghosh                 SegsSizes->total(), G.getName())));
77*4fcf8434SAnubhab Ghosh     return;
78*4fcf8434SAnubhab Ghosh   }
79*4fcf8434SAnubhab Ghosh 
80*4fcf8434SAnubhab Ghosh   Mapper->reserve(
81*4fcf8434SAnubhab Ghosh       SegsSizes->total(),
82*4fcf8434SAnubhab Ghosh       [this, &G, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
83*4fcf8434SAnubhab Ghosh           Expected<ExecutorAddrRange> Result) mutable {
84*4fcf8434SAnubhab Ghosh         if (!Result) {
85*4fcf8434SAnubhab Ghosh           return OnAllocated(Result.takeError());
86*4fcf8434SAnubhab Ghosh         }
87*4fcf8434SAnubhab Ghosh 
88*4fcf8434SAnubhab Ghosh         auto NextSegAddr = Result->Start;
89*4fcf8434SAnubhab Ghosh 
90*4fcf8434SAnubhab Ghosh         std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
91*4fcf8434SAnubhab Ghosh 
92*4fcf8434SAnubhab Ghosh         for (auto &KV : BL.segments()) {
93*4fcf8434SAnubhab Ghosh           auto &AG = KV.first;
94*4fcf8434SAnubhab Ghosh           auto &Seg = KV.second;
95*4fcf8434SAnubhab Ghosh 
96*4fcf8434SAnubhab Ghosh           auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
97*4fcf8434SAnubhab Ghosh 
98*4fcf8434SAnubhab Ghosh           Seg.Addr = NextSegAddr;
99*4fcf8434SAnubhab Ghosh           Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
100*4fcf8434SAnubhab Ghosh 
101*4fcf8434SAnubhab Ghosh           NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
102*4fcf8434SAnubhab Ghosh 
103*4fcf8434SAnubhab Ghosh           MemoryMapper::AllocInfo::SegInfo SI;
104*4fcf8434SAnubhab Ghosh           SI.Offset = Seg.Addr - Result->Start;
105*4fcf8434SAnubhab Ghosh           SI.ContentSize = Seg.ContentSize;
106*4fcf8434SAnubhab Ghosh           SI.ZeroFillSize = Seg.ZeroFillSize;
107*4fcf8434SAnubhab Ghosh           SI.Prot = (toSysMemoryProtectionFlags(AG.getMemProt()));
108*4fcf8434SAnubhab Ghosh           SI.WorkingMem = Seg.WorkingMem;
109*4fcf8434SAnubhab Ghosh 
110*4fcf8434SAnubhab Ghosh           SegInfos.push_back(SI);
111*4fcf8434SAnubhab Ghosh         }
112*4fcf8434SAnubhab Ghosh 
113*4fcf8434SAnubhab Ghosh         if (auto Err = BL.apply()) {
114*4fcf8434SAnubhab Ghosh           OnAllocated(std::move(Err));
115*4fcf8434SAnubhab Ghosh           return;
116*4fcf8434SAnubhab Ghosh         }
117*4fcf8434SAnubhab Ghosh 
118*4fcf8434SAnubhab Ghosh         OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
119*4fcf8434SAnubhab Ghosh                                                     std::move(SegInfos)));
120*4fcf8434SAnubhab Ghosh       });
121*4fcf8434SAnubhab Ghosh }
122*4fcf8434SAnubhab Ghosh 
deallocate(std::vector<FinalizedAlloc> Allocs,OnDeallocatedFunction OnDeallocated)123*4fcf8434SAnubhab Ghosh void MapperJITLinkMemoryManager::deallocate(
124*4fcf8434SAnubhab Ghosh     std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
125*4fcf8434SAnubhab Ghosh   std::vector<ExecutorAddr> Bases;
126*4fcf8434SAnubhab Ghosh   Bases.reserve(Allocs.size());
127*4fcf8434SAnubhab Ghosh   for (auto &FA : Allocs) {
128*4fcf8434SAnubhab Ghosh     Bases.push_back(FA.getAddress());
129*4fcf8434SAnubhab Ghosh     FA.release();
130*4fcf8434SAnubhab Ghosh   }
131*4fcf8434SAnubhab Ghosh   Mapper->release(Bases, std::move(OnDeallocated));
132*4fcf8434SAnubhab Ghosh }
133*4fcf8434SAnubhab Ghosh 
134*4fcf8434SAnubhab Ghosh } // end namespace orc
135*4fcf8434SAnubhab Ghosh } // end namespace llvm
136