LLVM 24.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
15
16#include <limits>
17
18using namespace llvm::jitlink;
19
20namespace llvm {
21namespace orc {
22
25public:
26
27 // FIXME: The C++98 initializer is an attempt to work around compile failures
28 // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
29 // We should be able to switch this back to member initialization once that
30 // issue is fixed.
39
41
43 ExecutorAddr AllocAddr, SegInfoMap Segs)
44 : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
45
46 void finalize(OnFinalizedFunction OnFinalize) override {
48 for (auto &KV : Segs) {
49 assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
51 KV.first,
52 KV.second.Addr,
53 alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
54 Parent.ES.getExecutorProcessControl().getPageSize()),
55 {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
56 }
57
58 // Transfer allocation actions.
59 std::swap(FR.Actions, G.allocActions());
60
61 Parent.B.Initialize(
62 [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
63 Expected<ExecutorAddr> InitializeKey) mutable {
64 // FIXME: Release abandoned alloc.
65 if (!InitializeKey)
66 return OnFinalize(InitializeKey.takeError());
67 OnFinalize(FinalizedAlloc(AllocAddr));
68 },
69 Parent.ES, Parent.B.Instance, FR);
70 }
71
72 void abandon(OnAbandonedFunction OnAbandoned) override {
73 // FIXME: Return memory to pool instead.
74 Parent.B.Release(std::move(OnAbandoned), Parent.ES, Parent.B.Instance,
75 ArrayRef<ExecutorAddr>(AllocAddr));
76 }
77
78private:
80 LinkGraph &G;
81 ExecutorAddr AllocAddr;
82 SegInfoMap Segs;
83};
84
87 namespace sps = rt::sps;
88 namespace sps_ci = rt::sps_ci;
89 auto &ES = JD.getExecutionSession();
90 Bindings B;
91 // Instance is the executor-side allocator object -- a data symbol passed as
92 // the first argument to each call, not a wrapper to proxy.
93 if (auto Err = lookupAndRecordAddrs(
95 {{ES.intern(sps_ci::SimpleNativeMemoryMapInstanceName),
96 &B.Instance}}))
97 return std::move(Err);
98 // The proxies resolve to the specs' default (SimpleNativeMemoryMap) names.
99 if (auto Err = rt::buildProxies(
104 return std::move(Err);
105 return std::make_unique<EPCGenericJITLinkMemoryManager>(ES, std::move(B));
106}
107
110 return Create(ES.getBootstrapJITDylib());
111}
112
114 LinkGraph &G,
115 OnAllocatedFunction OnAllocated) {
116 BasicLayout BL(G);
117
118 auto Pages = BL.getContiguousPageBasedLayoutSizes(
119 ES.getExecutorProcessControl().getPageSize());
120 if (!Pages)
121 return OnAllocated(Pages.takeError());
122
123 B.Reserve(
124 [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
125 Expected<ExecutorAddr> AllocAddr) mutable {
126 if (!AllocAddr)
127 return OnAllocated(AllocAddr.takeError());
128 completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
129 },
130 ES, B.Instance, Pages->total());
131}
132
134 std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
135 std::vector<ExecutorAddr> Bases;
136 Bases.reserve(Allocs.size());
137 for (auto &A : Allocs)
138 Bases.push_back(ExecutorAddr(A.getAddress()));
139 B.Release(std::move(OnDeallocated), ES, B.Instance, Bases);
140 for (auto &A : Allocs)
141 A.release();
142}
143
144void EPCGenericJITLinkMemoryManager::completeAllocation(
145 ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
146
148
149 ExecutorAddr NextSegAddr = AllocAddr;
150 for (auto &KV : BL.segments()) {
151 const auto &AG = KV.first;
152 auto &Seg = KV.second;
153
154 Seg.Addr = NextSegAddr;
155 KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
156 NextSegAddr +=
157 ExecutorAddrDiff(alignTo(Seg.ContentSize + Seg.ZeroFillSize,
159
160 auto &SegInfo = SegInfos[AG];
161 SegInfo.ContentSize = Seg.ContentSize;
162 SegInfo.ZeroFillSize = Seg.ZeroFillSize;
163 SegInfo.Addr = Seg.Addr;
164 SegInfo.WorkingMem = Seg.WorkingMem;
165 }
166
167 if (auto Err = BL.apply())
168 return OnAllocated(std::move(Err));
169
170 OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
171 std::move(SegInfos)));
172}
173
174} // end namespace orc
175} // 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
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
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)
EPCGenericJITLinkMemoryManager(ExecutionSession &ES, Bindings B)
Create an EPCGenericJITLinkMemoryManager instance from a given set of memory-manager bindings.
void deallocate(std::vector< FinalizedAlloc > Allocs, OnDeallocatedFunction OnDeallocated) override
Deallocate a list of allocation objects.
static Expected< std::unique_ptr< EPCGenericJITLinkMemoryManager > > Create(JITDylib &JD)
Create an EPCGenericJITLinkMemoryManager for the ORC runtime's SimpleNativeMemoryMap interface,...
void allocate(const jitlink::JITLinkDylib *JD, jitlink::LinkGraph &G, OnAllocatedFunction OnAllocated) override
Start the allocation process.
An ExecutionSession represents a running JIT program.
Definition Core.h:1111
ExecutorProcessControl & getExecutorProcessControl()
Get the ExecutorProcessControl object associated with this ExecutionSession.
Definition Core.h:1156
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:675
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
Definition Core.h:694
ProxyInit< FnT > proxyInit(Proxy< FnT > *P, typename Proxy< FnT >::DispatchFn Dispatch, StringRef Name, SymbolLookupFlags LookupFlags=SymbolLookupFlags::RequiredSymbol)
Definition Proxy.h:167
Error buildProxies(JITDylib &JD)
buildProxies base case.
Definition Proxy.h:188
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:153
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
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:878
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
The resolved controller-side handle to an executor-side memory manager: the address of the allocator ...
std::vector< SegFinalizeRequest > Segments