18#define DEBUG_TYPE "orc"
22namespace rt_bootstrap {
25 assert(Slabs.empty() &&
"shutdown not called?");
34 std::lock_guard<std::mutex> Lock(M);
35 assert(!Slabs.count(MB.base()) &&
"Duplicate allocation addr");
36 Slabs[MB.base()].Size =
Size;
48 "finalization request",
54 std::vector<sys::MemoryBlock> MBsToReset;
56 for (
auto &MB : MBsToReset)
66 RR.
End = std::max(RR.
End, Seg.Addr + Seg.Size);
71 formatv(
"Segment {0:x} content size ({1:x} bytes) "
72 "exceeds segment size ({2:x} bytes)",
73 Seg.Addr.getValue(), Seg.Content.size(), Seg.Size),
78 formatv(
"Segment {0:x} -- {1:x} crosses boundary of "
79 "allocation {2:x} -- {3:x}",
83 char *Mem = Seg.Addr.toPtr<
char *>();
84 if (!Seg.Content.empty())
85 memcpy(Mem, Seg.Content.data(), Seg.Content.size());
86 memset(Mem + Seg.Content.size(), 0, Seg.Size - Seg.Content.size());
87 assert(Seg.Size <= std::numeric_limits<size_t>::max());
94 MBsToReset.push_back(MB);
100 auto DeallocActions = runFinalizeActions(FR.
Actions);
102 return DeallocActions.takeError();
105 std::lock_guard<std::mutex> Lock(M);
106 auto Region = createRegionInfo(RR,
"In initialize");
108 return Region.takeError();
109 Region->DeallocActions = std::move(*DeallocActions);
119 const std::vector<ExecutorAddr> &InitKeys) {
123 std::vector<shared::WrapperFunctionCall> DeallocActions;
125 std::scoped_lock<std::mutex> Lock(M);
126 auto Slab = getSlabInfo(KeyAddr,
"In deinitialize");
128 Err =
joinErrors(std::move(Err), Slab.takeError());
132 auto RI = getRegionInfo(*Slab, KeyAddr,
"In deinitialize");
134 Err =
joinErrors(std::move(Err), RI.takeError());
138 DeallocActions = std::move(RI->DeallocActions);
142 runDeallocActions(std::move(DeallocActions)));
149 const std::vector<ExecutorAddr> &Bases) {
154 std::vector<shared::WrapperFunctionCall> DeallocActions;
158 std::scoped_lock<std::mutex> Lock(M);
160 auto SlabI = Slabs.find(
Base.toPtr<
void *>());
161 if (SlabI == Slabs.end()) {
165 " is not part of any reserved "
171 auto &Slab = SlabI->second;
173 for (
auto &[Addr,
Region] : Slab.Regions)
176 MB = {
Base.toPtr<
void *>(), Slab.Size};
181 Err =
joinErrors(std::move(Err), runDeallocActions(DeallocActions));
192 std::vector<ExecutorAddr> Bases;
194 std::scoped_lock<std::mutex> Lock(M);
195 for (
auto &[
Base, Slab] : Slabs)
206 M[Mangle.mangledCopy(sps_ci::SimpleNativeMemoryMapInstanceName)] =
208 M[Mangle.mangledCopy(sps_ci::MemMgrReserve::Name)] =
210 M[Mangle.mangledCopy(sps_ci::MemMgrInitialize::Name)] =
212 M[Mangle.mangledCopy(sps_ci::MemMgrDeinitialize::Name)] =
214 M[Mangle.mangledCopy(sps_ci::MemMgrRelease::Name)] =
220 auto MakeBadSlabError = [&]() {
222 Context +
", address " +
formatv(
"{0:x}",
A) +
223 " is not part of any reserved address range",
227 auto I = Slabs.upper_bound(
A.toPtr<
void *>());
228 if (
I == Slabs.begin())
229 return MakeBadSlabError();
233 return MakeBadSlabError();
239SimpleExecutorMemoryManager::getSlabInfo(ExecutorAddrRange R,
241 auto MakeBadSlabError = [&]() {
243 Context +
", range " +
formatv(
"{0:x}", R) +
244 " is not part of any reserved address range",
248 auto I = Slabs.upper_bound(R.Start.toPtr<
void *>());
249 if (
I == Slabs.begin())
250 return MakeBadSlabError();
254 return MakeBadSlabError();
259Expected<SimpleExecutorMemoryManager::RegionInfo &>
260SimpleExecutorMemoryManager::createRegionInfo(ExecutorAddrRange R,
263 auto Slab = getSlabInfo(R,
Context);
265 return Slab.takeError();
267 auto MakeBadRegionError = [&](ExecutorAddrRange
Other,
bool Prev) {
270 (Prev ?
"previous" :
"following") +
275 auto I = Slab->Regions.upper_bound(
R.Start);
276 if (
I != Slab->Regions.begin()) {
277 auto J = std::prev(
I);
278 ExecutorAddrRange PrevRange(J->first, J->second.Size);
279 if (PrevRange.overlaps(R))
280 return MakeBadRegionError(PrevRange,
true);
282 if (
I != Slab->Regions.end()) {
283 ExecutorAddrRange NextRange(
I->first,
I->second.Size);
284 if (NextRange.overlaps(R))
285 return MakeBadRegionError(NextRange,
false);
288 auto &RInfo = Slab->Regions[
R.Start];
289 RInfo.Size =
R.size();
293Expected<SimpleExecutorMemoryManager::RegionInfo &>
294SimpleExecutorMemoryManager::getRegionInfo(SlabInfo &Slab, ExecutorAddr
A,
296 auto I = Slab.Regions.find(
A);
297 if (
I == Slab.Regions.end())
300 " does not correspond to the start of any initialized region",
306Expected<SimpleExecutorMemoryManager::RegionInfo &>
307SimpleExecutorMemoryManager::getRegionInfo(ExecutorAddr
A, StringRef
Context) {
308 auto Slab = getSlabInfo(
A,
Context);
310 return Slab.takeError();
312 return getRegionInfo(*Slab,
A,
Context);
315llvm::orc::shared::CWrapperFunctionBuffer
316SimpleExecutorMemoryManager::reserveWrapper(
const char *ArgData,
318 return shared::WrapperFunction<rt::sps_ci::MemMgrReserve::SPSSig>::handle(
325llvm::orc::shared::CWrapperFunctionBuffer
326SimpleExecutorMemoryManager::initializeWrapper(
const char *ArgData,
328 return shared::WrapperFunction<rt::sps_ci::MemMgrInitialize::SPSSig>::handle(
335llvm::orc::shared::CWrapperFunctionBuffer
336SimpleExecutorMemoryManager::deinitializeWrapper(
const char *ArgData,
338 return shared::WrapperFunction<rt::sps_ci::MemMgrDeinitialize::SPSSig>::
339 handle(ArgData, ArgSize,
345llvm::orc::shared::CWrapperFunctionBuffer
346SimpleExecutorMemoryManager::releaseWrapper(
const char *ArgData,
348 return shared::WrapperFunction<rt::sps_ci::MemMgrRelease::SPSSig>::handle(
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_UNLIKELY(EXPR)
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
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.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Represent a constant reference to a string, i.e.
Triple - Helper class for working with autoconf configuration names.
Represents an address in the executor process.
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
Applies linker name-mangling for a target.
Error deinitialize(const std::vector< ExecutorAddr > &InitKeys)
Error release(const std::vector< ExecutorAddr > &Bases)
~SimpleExecutorMemoryManager() override
Error shutdown() override
Expected< ExecutorAddr > reserve(uint64_t Size)
Expected< ExecutorAddr > initialize(tpctypes::FinalizeRequest &FR)
void addBootstrapSymbols(StringMap< ExecutorAddr > &M) override
This class encapsulates the notion of a memory block which has an address and a size.
static LLVM_ABI std::error_code protectMappedMemory(const MemoryBlock &Block, unsigned Flags)
This method sets the protection flags for a block of memory to the state specified by /p Flags.
static LLVM_ABI std::error_code releaseMappedMemory(MemoryBlock &Block)
This method releases a block of memory that was allocated with the allocateMappedMemory method.
static LLVM_ABI void InvalidateInstructionCache(const void *Addr, size_t Len)
InvalidateInstructionCache - Before the JIT can run a block of code that has been emitted it must inv...
static LLVM_ABI MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)
This method allocates a block of memory that is suitable for loading dynamically generated code (e....
MethodWrapperHandler< RetT, ClassT, ArgTs... > makeMethodWrapperHandler(RetT(ClassT::*Method)(ArgTs...))
Create a MethodWrapperHandler object from the given method pointer.
uint64_t ExecutorAddrDiff
sys::Memory::ProtectionFlags toSysMemoryProtectionFlags(MemProt MP)
Convert a MemProt value to a corresponding sys::Memory::ProtectionFlags value.
LLVM_ABI std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
OutputIt copy(R &&Range, OutputIt Out)
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Represents an address range in the exceutor process.
ExecutorAddrDiff size() const
bool contains(ExecutorAddr Addr) const
std::vector< SegFinalizeRequest > Segments
shared::AllocActions Actions