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