LLVM 20.0.0git
EPCGenericJITLinkMemoryManager.cpp
Go to the documentation of this file.
1//===---- EPCGenericJITLinkMemoryManager.cpp -- Mem management via EPC ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
14
15#include <limits>
16
17using namespace llvm::jitlink;
18
19namespace llvm {
20namespace orc {
21
24public:
25
26 // FIXME: The C++98 initializer is an attempt to work around compile failures
27 // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
28 // We should be able to switch this back to member initialization once that
29 // issue is fixed.
30 struct SegInfo {
32
37 };
38
40
42 ExecutorAddr AllocAddr, SegInfoMap Segs)
43 : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
44
45 void finalize(OnFinalizedFunction OnFinalize) override {
47 for (auto &KV : Segs) {
48 assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
50 KV.first,
51 KV.second.Addr,
52 alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
53 Parent.EPC.getPageSize()),
54 {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
55 }
56
57 // Transfer allocation actions.
59
60 Parent.EPC.callSPSWrapperAsync<
62 Parent.SAs.Finalize,
63 [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
64 Error SerializationErr, Error FinalizeErr) mutable {
65 // FIXME: Release abandoned alloc.
66 if (SerializationErr) {
67 cantFail(std::move(FinalizeErr));
68 OnFinalize(std::move(SerializationErr));
69 } else if (FinalizeErr)
70 OnFinalize(std::move(FinalizeErr));
71 else
72 OnFinalize(FinalizedAlloc(AllocAddr));
73 },
74 Parent.SAs.Allocator, std::move(FR));
75 }
76
77 void abandon(OnAbandonedFunction OnAbandoned) override {
78 // FIXME: Return memory to pool instead.
79 Parent.EPC.callSPSWrapperAsync<
81 Parent.SAs.Deallocate,
82 [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
83 Error DeallocateErr) mutable {
84 if (SerializationErr) {
85 cantFail(std::move(DeallocateErr));
86 OnAbandoned(std::move(SerializationErr));
87 } else
88 OnAbandoned(std::move(DeallocateErr));
89 },
90 Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
91 }
92
93private:
95 LinkGraph &G;
96 ExecutorAddr AllocAddr;
97 SegInfoMap Segs;
98};
99
101 LinkGraph &G,
102 OnAllocatedFunction OnAllocated) {
103 BasicLayout BL(G);
104
105 auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
106 if (!Pages)
107 return OnAllocated(Pages.takeError());
108
110 SAs.Reserve,
111 [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
112 Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
113 if (SerializationErr) {
114 cantFail(AllocAddr.takeError());
115 return OnAllocated(std::move(SerializationErr));
116 }
117 if (!AllocAddr)
118 return OnAllocated(AllocAddr.takeError());
119
120 completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
121 },
122 SAs.Allocator, Pages->total());
123}
124
126 std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
129 SAs.Deallocate,
130 [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
131 Error DeallocErr) mutable {
132 if (SerErr) {
133 cantFail(std::move(DeallocErr));
134 OnDeallocated(std::move(SerErr));
135 } else
136 OnDeallocated(std::move(DeallocErr));
137 },
138 SAs.Allocator, Allocs);
139 for (auto &A : Allocs)
140 A.release();
141}
142
143void EPCGenericJITLinkMemoryManager::completeAllocation(
144 ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
145
147
148 ExecutorAddr NextSegAddr = AllocAddr;
149 for (auto &KV : BL.segments()) {
150 const auto &AG = KV.first;
151 auto &Seg = KV.second;
152
153 Seg.Addr = NextSegAddr;
154 KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
155 NextSegAddr += ExecutorAddrDiff(
156 alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
157
158 auto &SegInfo = SegInfos[AG];
159 SegInfo.ContentSize = Seg.ContentSize;
160 SegInfo.ZeroFillSize = Seg.ZeroFillSize;
161 SegInfo.Addr = Seg.Addr;
162 SegInfo.WorkingMem = Seg.WorkingMem;
163 }
164
165 if (auto Err = BL.apply())
166 return OnAllocated(std::move(Err));
167
168 OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
169 std::move(SegInfos)));
170}
171
172} // end namespace orc
173} // end namespace llvm
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define G(x, y, z)
Definition: MD5.cpp:56
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Tagged union holding either a T or a Error.
Definition: Error.h:481
void finalize(OnFinalizedFunction OnFinalize) override
Called to transfer working memory to the target and apply finalization.
void abandon(OnAbandonedFunction OnAbandoned) override
Called prior to finalization if the allocation should be abandoned.
InFlightAlloc(EPCGenericJITLinkMemoryManager &Parent, LinkGraph &G, ExecutorAddr AllocAddr, SegInfoMap Segs)
void deallocate(std::vector< FinalizedAlloc > Allocs, OnDeallocatedFunction OnDeallocated) override
Deallocate a list of allocation objects.
void allocate(const jitlink::JITLinkDylib *JD, jitlink::LinkGraph &G, OnAllocatedFunction OnAllocated) override
Start the allocation process.
Represents an address in the executor process.
void callSPSWrapperAsync(RunPolicyT &&Runner, ExecutorAddr WrapperFnAddr, SendResultT &&SendResult, const ArgTs &...Args)
Run a wrapper function using SPS to serialize the arguments and deserialize the results.
unsigned getPageSize() const
Get the page size for the target process.
unique_function is a type-erasing functor similar to std::function.
shared::SPSExpected< shared::SPSExecutorAddr >(shared::SPSExecutorAddr, uint64_t) SPSSimpleExecutorMemoryManagerReserveSignature
Definition: OrcRTBridge.h:64
shared::SPSError(shared::SPSExecutorAddr, shared::SPSFinalizeRequest) SPSSimpleExecutorMemoryManagerFinalizeSignature
Definition: OrcRTBridge.h:66
shared::SPSError(shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSSimpleExecutorMemoryManagerDeallocateSignature
Definition: OrcRTBridge.h:68
uint64_t ExecutorAddrDiff
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:756
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1856
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
std::vector< SegFinalizeRequest > Segments