LLVM 23.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
24 "orc_rt_SimpleNativeMemoryMap_Instance",
25 "orc_rt_SimpleNativeMemoryMap_reserve_sps_wrapper",
26 "orc_rt_SimpleNativeMemoryMap_initialize_sps_wrapper",
27 "orc_rt_SimpleNativeMemoryMap_deinitializeMultiple_sps_wrapper",
28 "orc_rt_SimpleNativeMemoryMap_releaseMultiple_sps_wrapper",
29};
30
33public:
34
35 // FIXME: The C++98 initializer is an attempt to work around compile failures
36 // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
37 // We should be able to switch this back to member initialization once that
38 // issue is fixed.
47
49
51 ExecutorAddr AllocAddr, SegInfoMap Segs)
52 : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
53
54 void finalize(OnFinalizedFunction OnFinalize) override {
56 for (auto &KV : Segs) {
57 assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
59 KV.first,
60 KV.second.Addr,
61 alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
62 Parent.EPC.getPageSize()),
63 {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
64 }
65
66 // Transfer allocation actions.
67 std::swap(FR.Actions, G.allocActions());
68
69 Parent.EPC.callSPSWrapperAsync<
71 Parent.SAs.Initialize,
72 [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
73 Error SerializationErr,
74 Expected<ExecutorAddr> InitializeKey) mutable {
75 // FIXME: Release abandoned alloc.
76 if (SerializationErr) {
77 cantFail(InitializeKey.takeError());
78 OnFinalize(std::move(SerializationErr));
79 } else if (!InitializeKey)
80 OnFinalize(InitializeKey.takeError());
81 else
82 OnFinalize(FinalizedAlloc(AllocAddr));
83 },
84 Parent.SAs.Allocator, std::move(FR));
85 }
86
87 void abandon(OnAbandonedFunction OnAbandoned) override {
88 // FIXME: Return memory to pool instead.
89 Parent.EPC.callSPSWrapperAsync<
91 Parent.SAs.Release,
92 [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
93 Error DeallocateErr) mutable {
94 if (SerializationErr) {
95 cantFail(std::move(DeallocateErr));
96 OnAbandoned(std::move(SerializationErr));
97 } else
98 OnAbandoned(std::move(DeallocateErr));
99 },
100 Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
101 }
102
103private:
105 LinkGraph &G;
106 ExecutorAddr AllocAddr;
107 SegInfoMap Segs;
108};
109
112 auto &ES = JD.getExecutionSession();
113 SymbolAddrs SAs;
114 if (auto Err = lookupAndRecordAddrs(
116 {
117 {ES.intern(SNs.AllocatorName), &SAs.Allocator},
118 {ES.intern(SNs.ReserveName), &SAs.Reserve},
119 {ES.intern(SNs.InitializeName), &SAs.Initialize},
120 {ES.intern(SNs.DeinitializeName), &SAs.Deinitialize},
121 {ES.intern(SNs.ReleaseName), &SAs.Release},
122 }))
123 return Err;
124 return std::make_unique<EPCGenericJITLinkMemoryManager>(
125 ES.getExecutorProcessControl(), SAs);
126}
127
132
134 LinkGraph &G,
135 OnAllocatedFunction OnAllocated) {
136 BasicLayout BL(G);
137
138 auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
139 if (!Pages)
140 return OnAllocated(Pages.takeError());
141
143 SAs.Reserve,
144 [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
145 Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
146 if (SerializationErr) {
147 cantFail(AllocAddr.takeError());
148 return OnAllocated(std::move(SerializationErr));
149 }
150 if (!AllocAddr)
151 return OnAllocated(AllocAddr.takeError());
152
153 completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
154 },
155 SAs.Allocator, Pages->total());
156}
157
159 std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
161 SAs.Release,
162 [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
163 Error DeallocErr) mutable {
164 if (SerErr) {
165 cantFail(std::move(DeallocErr));
166 OnDeallocated(std::move(SerErr));
167 } else
168 OnDeallocated(std::move(DeallocErr));
169 },
170 SAs.Allocator, Allocs);
171 for (auto &A : Allocs)
172 A.release();
173}
174
175void EPCGenericJITLinkMemoryManager::completeAllocation(
176 ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
177
179
180 ExecutorAddr NextSegAddr = AllocAddr;
181 for (auto &KV : BL.segments()) {
182 const auto &AG = KV.first;
183 auto &Seg = KV.second;
184
185 Seg.Addr = NextSegAddr;
186 KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
187 NextSegAddr += ExecutorAddrDiff(
188 alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
189
190 auto &SegInfo = SegInfos[AG];
191 SegInfo.ContentSize = Seg.ContentSize;
192 SegInfo.ZeroFillSize = Seg.ZeroFillSize;
193 SegInfo.Addr = Seg.Addr;
194 SegInfo.WorkingMem = Seg.WorkingMem;
195 }
196
197 if (auto Err = BL.apply())
198 return OnAllocated(std::move(Err));
199
200 OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
201 std::move(SegInfos)));
202}
203
204} // end namespace orc
205} // end namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define G(x, y, z)
Definition MD5.cpp:55
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
A specialized small-map for AllocGroups.
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.
EPCGenericJITLinkMemoryManager(ExecutorProcessControl &EPC, SymbolAddrs SAs)
Create an EPCGenericJITLinkMemoryManager instance from a given set of function addrs.
static const SymbolNames orc_rt_SimpleNativeMemoryMapSPSSymbols
Default symbol names for the ORC runtime's SimpleNativeMemoryMap SPS interface.
static Expected< std::unique_ptr< EPCGenericJITLinkMemoryManager > > Create(JITDylib &JD, SymbolNames SNs=orc_rt_SimpleNativeMemoryMapSPSSymbols)
Create an EPCGenericJITLinkMemoryManager using the given implementation symbol names.
An ExecutionSession represents a running JIT program.
Definition Core.h:1355
JITDylib & getBootstrapJITDylib()
Returns a reference to the bootstrap JITDylib.
Definition Core.h:1416
Represents an address in the executor process.
unsigned getPageSize() const
Get the page size for the target process.
Represents a JIT'd dynamic library.
Definition Core.h:919
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
Definition Core.h:938
shared::SPSExpected< shared::SPSExecutorAddr >(shared::SPSExecutorAddr, uint64_t) SPSSimpleExecutorMemoryManagerReserveSignature
Definition OrcRTBridge.h:76
shared::SPSExpected< shared::SPSExecutorAddr >(shared::SPSExecutorAddr, shared::SPSFinalizeRequest) SPSSimpleExecutorMemoryManagerInitializeSignature
Definition OrcRTBridge.h:79
shared::SPSError( shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSSimpleExecutorMemoryManagerReleaseSignature
Definition OrcRTBridge.h:84
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
Definition Core.h:182
uint64_t ExecutorAddrDiff
LLVM_ABI void lookupAndRecordAddrs(unique_function< void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder, std::vector< std::pair< SymbolStringPtr, ExecutorAddr * > > Pairs, SymbolLookupFlags LookupFlags=SymbolLookupFlags::RequiredSymbol)
Record addresses of the given symbols in the given ExecutorAddrs.
This is an optimization pass for GlobalISel generic memory operations.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
ArrayRef(const T &OneElt) -> ArrayRef< T >
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:1917
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872
Symbol addresses for memory management implementation.
Symbol names for memory management implementation.
std::vector< SegFinalizeRequest > Segments