1349cc55cSDimitry Andric //===---- EPCGenericJITLinkMemoryManager.cpp -- Mem management via EPC ----===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric
9349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
10349cc55cSDimitry Andric
11349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h"
12349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
13349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
14349cc55cSDimitry Andric
15349cc55cSDimitry Andric #include <limits>
16349cc55cSDimitry Andric
17349cc55cSDimitry Andric using namespace llvm::jitlink;
18349cc55cSDimitry Andric
19349cc55cSDimitry Andric namespace llvm {
20349cc55cSDimitry Andric namespace orc {
21349cc55cSDimitry Andric
22349cc55cSDimitry Andric class EPCGenericJITLinkMemoryManager::InFlightAlloc
23349cc55cSDimitry Andric : public jitlink::JITLinkMemoryManager::InFlightAlloc {
24349cc55cSDimitry Andric public:
25349cc55cSDimitry Andric
26349cc55cSDimitry Andric // FIXME: The C++98 initializer is an attempt to work around compile failures
27349cc55cSDimitry Andric // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
28349cc55cSDimitry Andric // We should be able to switch this back to member initialization once that
29349cc55cSDimitry Andric // issue is fixed.
30349cc55cSDimitry Andric struct SegInfo {
SegInfollvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo31349cc55cSDimitry Andric SegInfo() : WorkingMem(nullptr), ContentSize(0), ZeroFillSize(0) {}
32349cc55cSDimitry Andric
33349cc55cSDimitry Andric char *WorkingMem;
34349cc55cSDimitry Andric ExecutorAddr Addr;
35349cc55cSDimitry Andric uint64_t ContentSize;
36349cc55cSDimitry Andric uint64_t ZeroFillSize;
37349cc55cSDimitry Andric };
38349cc55cSDimitry Andric
39349cc55cSDimitry Andric using SegInfoMap = AllocGroupSmallMap<SegInfo>;
40349cc55cSDimitry Andric
InFlightAlloc(EPCGenericJITLinkMemoryManager & Parent,LinkGraph & G,ExecutorAddr AllocAddr,SegInfoMap Segs)41349cc55cSDimitry Andric InFlightAlloc(EPCGenericJITLinkMemoryManager &Parent, LinkGraph &G,
42349cc55cSDimitry Andric ExecutorAddr AllocAddr, SegInfoMap Segs)
43349cc55cSDimitry Andric : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
44349cc55cSDimitry Andric
finalize(OnFinalizedFunction OnFinalize)45349cc55cSDimitry Andric void finalize(OnFinalizedFunction OnFinalize) override {
46349cc55cSDimitry Andric tpctypes::FinalizeRequest FR;
47349cc55cSDimitry Andric for (auto &KV : Segs) {
48349cc55cSDimitry Andric assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
49349cc55cSDimitry Andric FR.Segments.push_back(tpctypes::SegFinalizeRequest{
50bdd1243dSDimitry Andric KV.first,
51349cc55cSDimitry Andric KV.second.Addr,
52349cc55cSDimitry Andric alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
53349cc55cSDimitry Andric Parent.EPC.getPageSize()),
54349cc55cSDimitry Andric {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
55349cc55cSDimitry Andric }
56349cc55cSDimitry Andric
57349cc55cSDimitry Andric // Transfer allocation actions.
5804eeddc0SDimitry Andric std::swap(FR.Actions, G.allocActions());
59349cc55cSDimitry Andric
60349cc55cSDimitry Andric Parent.EPC.callSPSWrapperAsync<
61349cc55cSDimitry Andric rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>(
62349cc55cSDimitry Andric Parent.SAs.Finalize,
63349cc55cSDimitry Andric [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
64349cc55cSDimitry Andric Error SerializationErr, Error FinalizeErr) mutable {
65349cc55cSDimitry Andric // FIXME: Release abandoned alloc.
66349cc55cSDimitry Andric if (SerializationErr) {
67349cc55cSDimitry Andric cantFail(std::move(FinalizeErr));
68349cc55cSDimitry Andric OnFinalize(std::move(SerializationErr));
69349cc55cSDimitry Andric } else if (FinalizeErr)
70349cc55cSDimitry Andric OnFinalize(std::move(FinalizeErr));
71349cc55cSDimitry Andric else
7204eeddc0SDimitry Andric OnFinalize(FinalizedAlloc(AllocAddr));
73349cc55cSDimitry Andric },
74349cc55cSDimitry Andric Parent.SAs.Allocator, std::move(FR));
75349cc55cSDimitry Andric }
76349cc55cSDimitry Andric
abandon(OnAbandonedFunction OnAbandoned)77349cc55cSDimitry Andric void abandon(OnAbandonedFunction OnAbandoned) override {
78349cc55cSDimitry Andric // FIXME: Return memory to pool instead.
79349cc55cSDimitry Andric Parent.EPC.callSPSWrapperAsync<
80349cc55cSDimitry Andric rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
81349cc55cSDimitry Andric Parent.SAs.Deallocate,
82349cc55cSDimitry Andric [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
83349cc55cSDimitry Andric Error DeallocateErr) mutable {
84349cc55cSDimitry Andric if (SerializationErr) {
85349cc55cSDimitry Andric cantFail(std::move(DeallocateErr));
86349cc55cSDimitry Andric OnAbandoned(std::move(SerializationErr));
87349cc55cSDimitry Andric } else
88349cc55cSDimitry Andric OnAbandoned(std::move(DeallocateErr));
89349cc55cSDimitry Andric },
90349cc55cSDimitry Andric Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
91349cc55cSDimitry Andric }
92349cc55cSDimitry Andric
93349cc55cSDimitry Andric private:
94349cc55cSDimitry Andric EPCGenericJITLinkMemoryManager &Parent;
95349cc55cSDimitry Andric LinkGraph &G;
96349cc55cSDimitry Andric ExecutorAddr AllocAddr;
97349cc55cSDimitry Andric SegInfoMap Segs;
98349cc55cSDimitry Andric };
99349cc55cSDimitry Andric
allocate(const JITLinkDylib * JD,LinkGraph & G,OnAllocatedFunction OnAllocated)100349cc55cSDimitry Andric void EPCGenericJITLinkMemoryManager::allocate(const JITLinkDylib *JD,
101349cc55cSDimitry Andric LinkGraph &G,
102349cc55cSDimitry Andric OnAllocatedFunction OnAllocated) {
103349cc55cSDimitry Andric BasicLayout BL(G);
104349cc55cSDimitry Andric
105349cc55cSDimitry Andric auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
106349cc55cSDimitry Andric if (!Pages)
107349cc55cSDimitry Andric return OnAllocated(Pages.takeError());
108349cc55cSDimitry Andric
109349cc55cSDimitry Andric EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorMemoryManagerReserveSignature>(
110349cc55cSDimitry Andric SAs.Reserve,
111349cc55cSDimitry Andric [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
112349cc55cSDimitry Andric Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
113349cc55cSDimitry Andric if (SerializationErr) {
114349cc55cSDimitry Andric cantFail(AllocAddr.takeError());
115349cc55cSDimitry Andric return OnAllocated(std::move(SerializationErr));
116349cc55cSDimitry Andric }
117349cc55cSDimitry Andric if (!AllocAddr)
118349cc55cSDimitry Andric return OnAllocated(AllocAddr.takeError());
119349cc55cSDimitry Andric
120349cc55cSDimitry Andric completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
121349cc55cSDimitry Andric },
122349cc55cSDimitry Andric SAs.Allocator, Pages->total());
123349cc55cSDimitry Andric }
124349cc55cSDimitry Andric
deallocate(std::vector<FinalizedAlloc> Allocs,OnDeallocatedFunction OnDeallocated)125349cc55cSDimitry Andric void EPCGenericJITLinkMemoryManager::deallocate(
126349cc55cSDimitry Andric std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
127349cc55cSDimitry Andric EPC.callSPSWrapperAsync<
128349cc55cSDimitry Andric rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
129349cc55cSDimitry Andric SAs.Deallocate,
130349cc55cSDimitry Andric [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
131349cc55cSDimitry Andric Error DeallocErr) mutable {
132349cc55cSDimitry Andric if (SerErr) {
133349cc55cSDimitry Andric cantFail(std::move(DeallocErr));
134349cc55cSDimitry Andric OnDeallocated(std::move(SerErr));
135349cc55cSDimitry Andric } else
136349cc55cSDimitry Andric OnDeallocated(std::move(DeallocErr));
137349cc55cSDimitry Andric },
138349cc55cSDimitry Andric SAs.Allocator, Allocs);
139349cc55cSDimitry Andric for (auto &A : Allocs)
140349cc55cSDimitry Andric A.release();
141349cc55cSDimitry Andric }
142349cc55cSDimitry Andric
completeAllocation(ExecutorAddr AllocAddr,BasicLayout BL,OnAllocatedFunction OnAllocated)143349cc55cSDimitry Andric void EPCGenericJITLinkMemoryManager::completeAllocation(
144349cc55cSDimitry Andric ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
145349cc55cSDimitry Andric
146349cc55cSDimitry Andric InFlightAlloc::SegInfoMap SegInfos;
147349cc55cSDimitry Andric
148349cc55cSDimitry Andric ExecutorAddr NextSegAddr = AllocAddr;
149349cc55cSDimitry Andric for (auto &KV : BL.segments()) {
150349cc55cSDimitry Andric const auto &AG = KV.first;
151349cc55cSDimitry Andric auto &Seg = KV.second;
152349cc55cSDimitry Andric
15304eeddc0SDimitry Andric Seg.Addr = NextSegAddr;
154349cc55cSDimitry Andric KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
155349cc55cSDimitry Andric NextSegAddr += ExecutorAddrDiff(
156349cc55cSDimitry Andric alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
157349cc55cSDimitry Andric
158349cc55cSDimitry Andric auto &SegInfo = SegInfos[AG];
159349cc55cSDimitry Andric SegInfo.ContentSize = Seg.ContentSize;
160349cc55cSDimitry Andric SegInfo.ZeroFillSize = Seg.ZeroFillSize;
161*06c3fb27SDimitry Andric SegInfo.Addr = Seg.Addr;
162349cc55cSDimitry Andric SegInfo.WorkingMem = Seg.WorkingMem;
163349cc55cSDimitry Andric }
164349cc55cSDimitry Andric
165349cc55cSDimitry Andric if (auto Err = BL.apply())
166349cc55cSDimitry Andric return OnAllocated(std::move(Err));
167349cc55cSDimitry Andric
168349cc55cSDimitry Andric OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
169349cc55cSDimitry Andric std::move(SegInfos)));
170349cc55cSDimitry Andric }
171349cc55cSDimitry Andric
172349cc55cSDimitry Andric } // end namespace orc
173349cc55cSDimitry Andric } // end namespace llvm
174