LLVM 24.0.0git
MapperJITLinkMemoryManager.h
Go to the documentation of this file.
1//===--------------- MapperJITLinkMemoryManager.h -*- C++ -*---------------===//
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//
9// Implements JITLinkMemoryManager using MemoryMapper
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_MAPPERJITLINKMEMORYMANAGER_H
14#define LLVM_EXECUTIONENGINE_ORC_MAPPERJITLINKMEMORYMANAGER_H
15
21#include <optional>
22
23namespace llvm {
24namespace orc {
25
28public:
29 /// If ColocatePerJITDylib is true each JITDylib draws from its own pool of
30 /// reservations, so all of a JITDylib's objects are colocated (kept within
31 /// range of each other for direct, e.g. 32-bit PC-relative, references). If
32 /// false (the default) a single shared pool is used for all JITDylibs.
33 MapperJITLinkMemoryManager(size_t ReservationGranularity,
34 std::unique_ptr<MemoryMapper> Mapper,
35 bool ColocatePerJITDylib = false);
36
37 template <class MemoryMapperType, class... Args>
39 CreateWithMapper(size_t ReservationGranularity, Args &&...A) {
40 auto Mapper = MemoryMapperType::Create(std::forward<Args>(A)...);
41 if (!Mapper)
42 return Mapper.takeError();
43
44 return std::make_unique<MapperJITLinkMemoryManager>(ReservationGranularity,
45 std::move(*Mapper));
46 }
47
48 /// The default per-slab reservation size used by
49 /// createColocatingInProcessMemoryManager: 1 GiB on 64-bit hosts, 10 MiB on
50 /// 32-bit hosts. This is address space that is reserved, not committed.
51 static constexpr size_t defaultSlabSize() {
52 if constexpr (sizeof(void *) >= 8)
53 return size_t(1) << 30; // 1 GiB on 64-bit hosts.
54 else
55 return size_t(10) << 20; // 10 MiB on 32-bit hosts.
56 }
57
58 /// The reservation granularity passed to the constructor: each slab
59 /// reserved from the executor address space is a multiple of this.
60 size_t reservationUnits() const { return ReservationUnits; }
61
62 void allocate(const jitlink::JITLinkDylib *JD, jitlink::LinkGraph &G,
63 OnAllocatedFunction OnAllocated) override;
64 // synchronous overload
65 using JITLinkMemoryManager::allocate;
66
67 void deallocate(std::vector<FinalizedAlloc> Allocs,
68 OnDeallocatedFunction OnDeallocated) override;
69 // synchronous overload
70 using JITLinkMemoryManager::deallocate;
71
72 /// Policy invoked before reserving an additional slab for a JITDylib (i.e.
73 /// when its existing reservations can't satisfy a request). JD and
74 /// RequestedSize identify the JITDylib and reservation size behind the
75 /// request, for use in diagnostics. Returning an Error fails the
76 /// triggering allocation.
78 const jitlink::JITLinkDylib *JD, size_t RequestedSize)>;
79
80 /// Restrict each JITDylib to a single reservation ("slab"). Once a
81 /// JITDylib's slab is full, further allocations for it fail rather than
82 /// silently spilling into another, possibly out-of-range, slab.
83 void denySlabGrowth();
84
85 /// Allow each JITDylib to grow into additional reservations on demand (the
86 /// default). Objects in different slabs of the same JITDylib are not
87 /// guaranteed to be within range of each other.
88 ///
89 /// Note: LLJITBuilder::setColocatingSlabAllocator() overrides this default
90 /// to denySlabGrowth() when no SlabGrowthPolicy is given.
91 void allowSlabGrowth();
92
93 /// Set a custom slab-growth policy. See SlabGrowthPolicy above.
95
96 /// Called when a registered JITDylib is destroyed (see
97 /// jitlink::JITLinkDylib::notifyOnDestruction). Frees its pool so a new
98 /// JITDylib at the same (reused) address doesn't inherit stale state.
99 void notifyDestroying(jitlink::JITLinkDylib &JD) override;
100
101private:
102 class InFlightAlloc;
103
104 using AvailableMemoryMap = IntervalMap<ExecutorAddr, bool>;
105
106 // Returns the pool of reserved-but-not-yet-allocated ranges for the given
107 // key, creating it on first use. The key is the JITDylib when colocating
108 // per-JITDylib, otherwise nullptr (a single shared pool). Must be called with
109 // Mutex held.
110 AvailableMemoryMap &
111 getAvailableMemoryLocked(const jitlink::JITLinkDylib *Key);
112
113 std::mutex Mutex;
114
115 // We reserve multiples of this from the executor address space
116 size_t ReservationUnits;
117
118 // When true, each JITDylib gets its own pool of reservations (so a
119 // JITDylib's objects are colocated); when false a single nullptr-keyed pool
120 // is shared by all JITDylibs.
121 bool ColocatePerJITDylib;
122
123 // Policy consulted before reserving an additional slab for a pool (i.e. when
124 // a pool already owns a reservation but none of its free ranges fit the
125 // request). Returning an Error fails the allocation. Defaults to allowing
126 // additional slabs (preserving the historical behavior).
127 SlabGrowthPolicy OnSlabGrow = [](const jitlink::JITLinkDylib *,
128 size_t) -> Error {
129 return Error::success();
130 };
131
132 AvailableMemoryMap::Allocator AMAllocator;
133
134 // Per-key pool state: the reserved-but-not-yet-allocated ranges available
135 // for reuse, and whether the pool already owns at least one reservation
136 // (used to detect when a further reservation would be another slab for it).
137 // Both live in one map, keyed the same way, so they can't get out of sync
138 // with each other.
139 struct PoolInfo {
140 // The unique_ptr keeps each IntervalMap at a stable address as the map
141 // grows, so references returned by getAvailableMemoryLocked() stay valid.
142 std::unique_ptr<AvailableMemoryMap> AvailPool;
143 bool Reserved = false;
144 };
146
147 // Ranges that have been reserved and already allocated: base address -> size.
149
150 // Base address -> the pool key the allocation was drawn from, so that
151 // deallocate() can return the range to the right pool.
153
154 std::unique_ptr<MemoryMapper> Mapper;
155};
156
157/// Create an in-process slab allocator that colocates each JITDylib's objects
158/// within its own reservation(s). If ReservationGranularity is not given,
159/// MapperJITLinkMemoryManager::defaultSlabSize() is used.
160LLVM_ABI Expected<std::unique_ptr<MapperJITLinkMemoryManager>>
162 std::optional<size_t> ReservationGranularity = std::nullopt);
163
164} // end namespace orc
165} // end namespace llvm
166
167#endif // LLVM_EXECUTIONENGINE_ORC_MAPPERJITLINKMEMORYMANAGER_H
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_ABI
Definition Compiler.h:211
This file provides a collection of function (or more generally, callable) type erasure utilities supp...
This file implements a coalescing interval map for small objects.
#define G(x, y, z)
Definition MD5.cpp:55
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
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,...
static Expected< std::unique_ptr< MapperJITLinkMemoryManager > > CreateWithMapper(size_t ReservationGranularity, Args &&...A)
size_t reservationUnits() const
The reservation granularity passed to the constructor: each slab reserved from the executor address s...
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).
unique_function is a type-erasing functor similar to std::function.
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.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key