25 std::vector<MemoryMapper::AllocInfo::SegInfo> Segs)
26 : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(
std::
move(Segs)) {}
35 Parent.Mapper->initialize(AI, [OnFinalize = std::move(OnFinalize)](
38 OnFinalize(
Result.takeError());
47 Parent.Mapper->deinitialize({AllocAddr}, std::move(OnFinalize));
54 std::vector<MemoryMapper::AllocInfo::SegInfo> Segs;
58 size_t ReservationGranularity, std::unique_ptr<MemoryMapper> Mapper,
59 bool ColocatePerJITDylib)
60 : ReservationUnits(ReservationGranularity),
61 ColocatePerJITDylib(ColocatePerJITDylib), Mapper(
std::
move(Mapper)) {}
68MapperJITLinkMemoryManager::AvailableMemoryMap &
69MapperJITLinkMemoryManager::getAvailableMemoryLocked(
const JITLinkDylib *
Key) {
70 auto [It, Inserted] = Pools.try_emplace(
Key);
73 auto &Pool = It->second.AvailPool;
75 Pool = std::make_unique<AvailableMemoryMap>(AMAllocator);
80 std::lock_guard<std::mutex> Lock(Mutex);
85 std::lock_guard<std::mutex> Lock(Mutex);
88 "JITDylib '%s' slab exhausted (single-slab mode); enable slab "
89 "growth to allow further reservations (%zu bytes requested)",
90 JD ? JD->
getName().c_str() :
"<unnamed>", RequestedSize);
95 std::lock_guard<std::mutex> Lock(Mutex);
102 std::lock_guard<std::mutex> Lock(Mutex);
103 OnSlabGrow = std::move(Policy);
108 std::optional<size_t> ReservationGranularity) {
111 return Mapper.takeError();
112 return std::make_unique<MapperJITLinkMemoryManager>(
113 ReservationGranularity.value_or(
126 OnAllocated(SegsSizes.takeError());
130 auto TotalSize = SegsSizes->total();
134 const JITLinkDylib *PoolKey = ColocatePerJITDylib ? JD :
nullptr;
136 auto CompleteAllocation = [
this, PoolKey, &
G, BL = std::move(BL),
137 OnAllocated = std::move(OnAllocated)](
141 return OnAllocated(
Result.takeError());
144 auto NextSegAddr =
Result->Start;
146 std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
150 auto &Seg = KV.second;
152 auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
154 Seg.Addr = NextSegAddr;
155 Seg.WorkingMem = Mapper->prepare(
G, NextSegAddr, TotalSize);
157 NextSegAddr +=
alignTo(TotalSize, Mapper->getPageSize());
160 SI.Offset = Seg.Addr -
Result->Start;
161 SI.ContentSize = Seg.ContentSize;
162 SI.ZeroFillSize = Seg.ZeroFillSize;
164 SI.WorkingMem = Seg.WorkingMem;
166 SegInfos.push_back(
SI);
169 UsedMemory.insert({
Result->Start, NextSegAddr -
Result->Start});
170 AllocPoolKey[
Result->Start] = PoolKey;
172 if (NextSegAddr < Result->
End) {
175 getAvailableMemoryLocked(PoolKey).insert(NextSegAddr,
Result->End - 1,
180 if (
auto Err = BL.
apply()) {
181 OnAllocated(std::move(Err));
185 OnAllocated(std::make_unique<InFlightAlloc>(*
this,
G,
Result->Start,
186 std::move(SegInfos)));
194 AvailableMemoryMap &Avail = getAvailableMemoryLocked(PoolKey);
195 for (AvailableMemoryMap::iterator It = Avail.
begin(); It != Avail.
end();
197 if (It.stop() - It.start() + 1 >= TotalSize) {
204 if (SelectedRange.
empty()) {
208 bool IsFirstReservation = !Pools[PoolKey].Reserved;
209 Pools[PoolKey].Reserved =
true;
210 auto TotalAllocation =
alignTo(TotalSize, ReservationUnits);
211 if (!IsFirstReservation) {
212 if (
auto Err = OnSlabGrow(JD, TotalAllocation))
213 return CompleteAllocation(std::move(Err));
215 Mapper->reserve(TotalAllocation,
216 [
this, PoolKey, IsFirstReservation,
217 CompleteAllocation = std::move(CompleteAllocation)](
224 if (!
Result && IsFirstReservation)
225 Pools[PoolKey].Reserved =
false;
226 CompleteAllocation(std::move(
Result));
229 CompleteAllocation(SelectedRange);
235 std::vector<ExecutorAddr> Bases;
236 Bases.reserve(Allocs.size());
237 for (
auto &FA : Allocs) {
239 Bases.push_back(Addr);
242 Mapper->deinitialize(Bases, [
this, Allocs = std::move(Allocs),
243 OnDeallocated = std::move(OnDeallocated)](
250 for (
auto &FA : Allocs)
252 OnDeallocated(std::move(Err));
257 std::lock_guard<std::mutex> Lock(Mutex);
259 for (
auto &FA : Allocs) {
263 UsedMemory.erase(Addr);
266 const JITLinkDylib *PoolKey = AllocPoolKey.lookup(Addr);
267 AllocPoolKey.erase(Addr);
268 getAvailableMemoryLocked(PoolKey).insert(Addr, Addr +
Size - 1,
true);
Provides a library for accessing information about this process and other processes on the operating ...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
const_iterator begin() const
const_iterator end() const
BasicLayout simplifies the implementation of JITLinkMemoryManagers.
LLVM_ABI Error apply()
Apply the layout to the graph.
LLVM_ABI Expected< ContiguousPageBasedLayoutSizes > getContiguousPageBasedLayoutSizes(uint64_t PageSize)
Returns the total number of required to allocate all segments (with each segment padded out to page s...
iterator_range< SegmentMap::iterator > segments()
Returns an iterator over the segments of the layout.
Represents a JITDylib as seen by JITLink.
const std::string & getName() const
Get the name for this JITLinkDylib.
Represents a finalized allocation.
Represents an allocation which has not been finalized yet.
unique_function< void(Error)> OnAbandonedFunction
unique_function< void(Expected< FinalizedAlloc >)> OnFinalizedFunction
unique_function< void(AllocResult)> OnAllocatedFunction
Called when allocation has been completed.
unique_function< void(Error)> OnDeallocatedFunction
Called when deallocation has completed.
Represents an address in the executor process.
static Expected< std::unique_ptr< InProcessMemoryMapper > > Create()
InFlightAlloc(MapperJITLinkMemoryManager &Parent, LinkGraph &G, ExecutorAddr AllocAddr, std::vector< MemoryMapper::AllocInfo::SegInfo > Segs)
void finalize(OnFinalizedFunction OnFinalize) override
Called to transfer working memory to the target and apply finalization.
void abandon(OnAbandonedFunction OnFinalize) override
Called prior to finalization if the allocation should be abandoned.
void deallocate(std::vector< FinalizedAlloc > Allocs, OnDeallocatedFunction OnDeallocated) override
Deallocate a list of allocation objects.
MapperJITLinkMemoryManager(size_t ReservationGranularity, std::unique_ptr< MemoryMapper > Mapper, bool ColocatePerJITDylib=false)
If ColocatePerJITDylib is true each JITDylib draws from its own pool of reservations,...
void allowSlabGrowth()
Allow each JITDylib to grow into additional reservations on demand (the default).
static constexpr size_t defaultSlabSize()
The default per-slab reservation size used by createColocatingInProcessMemoryManager: 1 GiB on 64-bit...
unique_function< Error( const jitlink::JITLinkDylib *JD, size_t RequestedSize)> SlabGrowthPolicy
Policy invoked before reserving an additional slab for a JITDylib (i.e.
void setSlabPolicy(SlabGrowthPolicy Policy)
Set a custom slab-growth policy. See SlabGrowthPolicy above.
void denySlabGrowth()
Restrict each JITDylib to a single reservation ("slab").
void notifyDestroying(jitlink::JITLinkDylib &JD) override
Called when a registered JITDylib is destroyed (see jitlink::JITLinkDylib::notifyOnDestruction).
void allocate(const jitlink::JITLinkDylib *JD, jitlink::LinkGraph &G, OnAllocatedFunction OnAllocated) override
Start the allocation process.
uint64_t ExecutorAddrDiff
LLVM_ABI Expected< std::unique_ptr< MapperJITLinkMemoryManager > > createColocatingInProcessMemoryManager(std::optional< size_t > ReservationGranularity=std::nullopt)
Create an in-process slab allocator that colocates each JITDylib's objects within its own reservation...
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
@ End
Run the machine verifier once, at the end of the pipeline.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Represents an address range in the exceutor process.
Represents a single allocation containing multiple segments and initialization and deinitialization a...
std::vector< SegInfo > Segments
shared::AllocActions Actions