Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.0.0git
SimpleExecutorMemoryManager.cpp
Go to the documentation of this file.
1//===- SimpleExecuorMemoryManagare.cpp - Simple executor-side memory mgmt -===//
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#include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.h"
10
11#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12#include "llvm/Support/FormatVariadic.h"
13
14#define DEBUG_TYPE "orc"
15
16namespacellvm {
17namespaceorc {
18namespacert_bootstrap {
19
20SimpleExecutorMemoryManager::~SimpleExecutorMemoryManager() {
21assert(Allocations.empty() &&"shutdown not called?");
22}
23
24Expected<ExecutorAddr>SimpleExecutorMemoryManager::allocate(uint64_tSize) {
25 std::error_code EC;
26auto MB =sys::Memory::allocateMappedMemory(
27Size,nullptr,sys::Memory::MF_READ |sys::Memory::MF_WRITE, EC);
28if (EC)
29returnerrorCodeToError(EC);
30 std::lock_guard<std::mutex> Lock(M);
31assert(!Allocations.count(MB.base()) &&"Duplicate allocation addr");
32 Allocations[MB.base()].Size =Size;
33returnExecutorAddr::fromPtr(MB.base());
34}
35
36ErrorSimpleExecutorMemoryManager::finalize(tpctypes::FinalizeRequest &FR) {
37ExecutorAddrBase(~0ULL);
38 std::vector<shared::WrapperFunctionCall> DeallocationActions;
39size_t SuccessfulFinalizationActions = 0;
40
41if (FR.Segments.empty()) {
42// NOTE: Finalizing nothing is currently a no-op. Should it be an error?
43if (FR.Actions.empty())
44returnError::success();
45else
46return make_error<StringError>("Finalization actions attached to empty "
47"finalization request",
48inconvertibleErrorCode());
49 }
50
51for (auto &Seg : FR.Segments)
52Base = std::min(Base, Seg.Addr);
53
54for (auto &ActPair : FR.Actions)
55if (ActPair.Dealloc)
56 DeallocationActions.push_back(ActPair.Dealloc);
57
58// Get the Allocation for this finalization.
59size_t AllocSize = 0;
60 {
61 std::lock_guard<std::mutex> Lock(M);
62autoI = Allocations.find(Base.toPtr<void *>());
63if (I == Allocations.end())
64return make_error<StringError>("Attempt to finalize unrecognized "
65"allocation " +
66formatv("{0:x}",Base.getValue()),
67inconvertibleErrorCode());
68 AllocSize =I->second.Size;
69I->second.DeallocationActions = std::move(DeallocationActions);
70 }
71ExecutorAddr AllocEnd =Base +ExecutorAddrDiff(AllocSize);
72
73// Bail-out function: this will run deallocation actions corresponding to any
74// completed finalization actions, then deallocate memory.
75auto BailOut = [&](Error Err) {
76 std::pair<void *, Allocation> AllocToDestroy;
77
78// Get allocation to destroy.
79 {
80 std::lock_guard<std::mutex> Lock(M);
81autoI = Allocations.find(Base.toPtr<void *>());
82
83// Check for missing allocation (effective a double free).
84if (I == Allocations.end())
85returnjoinErrors(
86 std::move(Err),
87 make_error<StringError>("No allocation entry found "
88"for " +
89formatv("{0:x}",Base.getValue()),
90inconvertibleErrorCode()));
91 AllocToDestroy = std::move(*I);
92 Allocations.erase(I);
93 }
94
95// Run deallocation actions for all completed finalization actions.
96while (SuccessfulFinalizationActions)
97 Err =
98joinErrors(std::move(Err), FR.Actions[--SuccessfulFinalizationActions]
99 .Dealloc.runWithSPSRetErrorMerged());
100
101// Deallocate memory.
102sys::MemoryBlock MB(AllocToDestroy.first, AllocToDestroy.second.Size);
103if (auto EC =sys::Memory::releaseMappedMemory(MB))
104 Err =joinErrors(std::move(Err),errorCodeToError(EC));
105
106return Err;
107 };
108
109// Copy content and apply permissions.
110for (auto &Seg : FR.Segments) {
111
112// Check segment ranges.
113if (LLVM_UNLIKELY(Seg.Size < Seg.Content.size()))
114return BailOut(make_error<StringError>(
115formatv("Segment {0:x} content size ({1:x} bytes) "
116"exceeds segment size ({2:x} bytes)",
117 Seg.Addr.getValue(), Seg.Content.size(), Seg.Size),
118inconvertibleErrorCode()));
119ExecutorAddr SegEnd = Seg.Addr +ExecutorAddrDiff(Seg.Size);
120if (LLVM_UNLIKELY(Seg.Addr <Base || SegEnd > AllocEnd))
121return BailOut(make_error<StringError>(
122formatv("Segment {0:x} -- {1:x} crosses boundary of "
123"allocation {2:x} -- {3:x}",
124 Seg.Addr.getValue(), SegEnd.getValue(),Base.getValue(),
125 AllocEnd.getValue()),
126inconvertibleErrorCode()));
127
128char *Mem = Seg.Addr.toPtr<char *>();
129if (!Seg.Content.empty())
130 memcpy(Mem, Seg.Content.data(), Seg.Content.size());
131 memset(Mem + Seg.Content.size(), 0, Seg.Size - Seg.Content.size());
132assert(Seg.Size <= std::numeric_limits<size_t>::max());
133if (auto EC =sys::Memory::protectMappedMemory(
134 {Mem,static_cast<size_t>(Seg.Size)},
135toSysMemoryProtectionFlags(Seg.RAG.Prot)))
136return BailOut(errorCodeToError(EC));
137if ((Seg.RAG.Prot &MemProt::Exec) ==MemProt::Exec)
138sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
139 }
140
141// Run finalization actions.
142for (auto &ActPair : FR.Actions) {
143if (auto Err = ActPair.Finalize.runWithSPSRetErrorMerged())
144return BailOut(std::move(Err));
145 ++SuccessfulFinalizationActions;
146 }
147
148returnError::success();
149}
150
151ErrorSimpleExecutorMemoryManager::deallocate(
152const std::vector<ExecutorAddr> &Bases) {
153 std::vector<std::pair<void *, Allocation>> AllocPairs;
154 AllocPairs.reserve(Bases.size());
155
156// Get allocation to destroy.
157Error Err =Error::success();
158 {
159 std::lock_guard<std::mutex> Lock(M);
160for (auto &Base : Bases) {
161autoI = Allocations.find(Base.toPtr<void *>());
162
163// Check for missing allocation (effective a double free).
164if (I != Allocations.end()) {
165 AllocPairs.push_back(std::move(*I));
166 Allocations.erase(I);
167 }else
168 Err =joinErrors(
169 std::move(Err),
170 make_error<StringError>("No allocation entry found "
171"for " +
172formatv("{0:x}",Base.getValue()),
173inconvertibleErrorCode()));
174 }
175 }
176
177while (!AllocPairs.empty()) {
178auto &P = AllocPairs.back();
179 Err =joinErrors(std::move(Err), deallocateImpl(P.first,P.second));
180 AllocPairs.pop_back();
181 }
182
183return Err;
184}
185
186ErrorSimpleExecutorMemoryManager::shutdown() {
187
188AllocationsMap AM;
189 {
190 std::lock_guard<std::mutex> Lock(M);
191 AM = std::move(Allocations);
192 }
193
194Error Err =Error::success();
195for (auto &KV : AM)
196 Err =joinErrors(std::move(Err), deallocateImpl(KV.first, KV.second));
197return Err;
198}
199
200voidSimpleExecutorMemoryManager::addBootstrapSymbols(
201StringMap<ExecutorAddr> &M) {
202 M[rt::SimpleExecutorMemoryManagerInstanceName] =ExecutorAddr::fromPtr(this);
203 M[rt::SimpleExecutorMemoryManagerReserveWrapperName] =
204ExecutorAddr::fromPtr(&reserveWrapper);
205 M[rt::SimpleExecutorMemoryManagerFinalizeWrapperName] =
206ExecutorAddr::fromPtr(&finalizeWrapper);
207 M[rt::SimpleExecutorMemoryManagerDeallocateWrapperName] =
208ExecutorAddr::fromPtr(&deallocateWrapper);
209}
210
211Error SimpleExecutorMemoryManager::deallocateImpl(void *Base, Allocation &A) {
212Error Err =Error::success();
213
214while (!A.DeallocationActions.empty()) {
215 Err =joinErrors(std::move(Err),
216A.DeallocationActions.back().runWithSPSRetErrorMerged());
217A.DeallocationActions.pop_back();
218 }
219
220sys::MemoryBlock MB(Base,A.Size);
221if (auto EC =sys::Memory::releaseMappedMemory(MB))
222 Err =joinErrors(std::move(Err),errorCodeToError(EC));
223
224return Err;
225}
226
227llvm::orc::shared::CWrapperFunctionResult
228SimpleExecutorMemoryManager::reserveWrapper(constchar *ArgData,
229size_t ArgSize) {
230return shared::WrapperFunction<
231rt::SPSSimpleExecutorMemoryManagerReserveSignature>::
232 handle(ArgData, ArgSize,
233shared::makeMethodWrapperHandler(
234 &SimpleExecutorMemoryManager::allocate))
235 .release();
236}
237
238llvm::orc::shared::CWrapperFunctionResult
239SimpleExecutorMemoryManager::finalizeWrapper(constchar *ArgData,
240size_t ArgSize) {
241return shared::WrapperFunction<
242rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>::
243 handle(ArgData, ArgSize,
244shared::makeMethodWrapperHandler(
245 &SimpleExecutorMemoryManager::finalize))
246 .release();
247}
248
249llvm::orc::shared::CWrapperFunctionResult
250SimpleExecutorMemoryManager::deallocateWrapper(constchar *ArgData,
251size_t ArgSize) {
252return shared::WrapperFunction<
253rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>::
254 handle(ArgData, ArgSize,
255shared::makeMethodWrapperHandler(
256 &SimpleExecutorMemoryManager::deallocate))
257 .release();
258}
259
260}// namespace rt_bootstrap
261}// end namespace orc
262}// end namespace llvm
A
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
LLVM_UNLIKELY
#define LLVM_UNLIKELY(EXPR)
Definition:Compiler.h:320
Size
uint64_t Size
Definition:ELFObjHandler.cpp:81
FormatVariadic.h
I
#define I(x, y, z)
Definition:MD5.cpp:58
P
#define P(N)
OrcRTBridge.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SimpleExecutorMemoryManager.h
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition:DenseMap.h:156
llvm::DenseMapBase::erase
bool erase(const KeyT &Val)
Definition:DenseMap.h:321
llvm::DenseMapBase::empty
bool empty() const
Definition:DenseMap.h:98
llvm::DenseMapBase::count
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition:DenseMap.h:152
llvm::DenseMapBase::end
iterator end()
Definition:DenseMap.h:84
llvm::DenseMap< void *, Allocation >
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition:Error.h:160
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition:Error.h:337
llvm::Expected
Tagged union holding either a T or a Error.
Definition:Error.h:481
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition:StringMap.h:128
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition:ExecutorAddress.h:34
llvm::orc::ExecutorAddr::getValue
uint64_t getValue() const
Definition:ExecutorAddress.h:136
llvm::orc::ExecutorAddr::fromPtr
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
Definition:ExecutorAddress.h:111
llvm::orc::rt_bootstrap::SimpleExecutorMemoryManager::finalize
Error finalize(tpctypes::FinalizeRequest &FR)
Definition:SimpleExecutorMemoryManager.cpp:36
llvm::orc::rt_bootstrap::SimpleExecutorMemoryManager::deallocate
Error deallocate(const std::vector< ExecutorAddr > &Bases)
Definition:SimpleExecutorMemoryManager.cpp:151
llvm::orc::rt_bootstrap::SimpleExecutorMemoryManager::shutdown
Error shutdown() override
Definition:SimpleExecutorMemoryManager.cpp:186
llvm::orc::rt_bootstrap::SimpleExecutorMemoryManager::allocate
Expected< ExecutorAddr > allocate(uint64_t Size)
Definition:SimpleExecutorMemoryManager.cpp:24
llvm::orc::rt_bootstrap::SimpleExecutorMemoryManager::~SimpleExecutorMemoryManager
virtual ~SimpleExecutorMemoryManager()
Definition:SimpleExecutorMemoryManager.cpp:20
llvm::orc::rt_bootstrap::SimpleExecutorMemoryManager::addBootstrapSymbols
void addBootstrapSymbols(StringMap< ExecutorAddr > &M) override
Definition:SimpleExecutorMemoryManager.cpp:200
llvm::sys::MemoryBlock
This class encapsulates the notion of a memory block which has an address and a size.
Definition:Memory.h:32
llvm::sys::Memory::releaseMappedMemory
static std::error_code releaseMappedMemory(MemoryBlock &Block)
This method releases a block of memory that was allocated with the allocateMappedMemory method.
llvm::sys::Memory::allocateMappedMemory
static 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....
llvm::sys::Memory::MF_READ
@ MF_READ
Definition:Memory.h:56
llvm::sys::Memory::MF_WRITE
@ MF_WRITE
Definition:Memory.h:57
llvm::sys::Memory::InvalidateInstructionCache
static 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...
llvm::sys::Memory::protectMappedMemory
static 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.
uint64_t
llvm::orc::rt::SPSSimpleExecutorMemoryManagerReserveSignature
shared::SPSExpected< shared::SPSExecutorAddr >(shared::SPSExecutorAddr, uint64_t) SPSSimpleExecutorMemoryManagerReserveSignature
Definition:OrcRTBridge.h:65
llvm::orc::rt::SimpleExecutorMemoryManagerFinalizeWrapperName
const char * SimpleExecutorMemoryManagerFinalizeWrapperName
Definition:OrcRTBridge.cpp:26
llvm::orc::rt::SimpleExecutorMemoryManagerDeallocateWrapperName
const char * SimpleExecutorMemoryManagerDeallocateWrapperName
Definition:OrcRTBridge.cpp:28
llvm::orc::rt::SimpleExecutorMemoryManagerReserveWrapperName
const char * SimpleExecutorMemoryManagerReserveWrapperName
Definition:OrcRTBridge.cpp:24
llvm::orc::rt::SPSSimpleExecutorMemoryManagerFinalizeSignature
shared::SPSError(shared::SPSExecutorAddr, shared::SPSFinalizeRequest) SPSSimpleExecutorMemoryManagerFinalizeSignature
Definition:OrcRTBridge.h:67
llvm::orc::rt::SimpleExecutorMemoryManagerInstanceName
const char * SimpleExecutorMemoryManagerInstanceName
Definition:OrcRTBridge.cpp:22
llvm::orc::rt::SPSSimpleExecutorMemoryManagerDeallocateSignature
shared::SPSError(shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSSimpleExecutorMemoryManagerDeallocateSignature
Definition:OrcRTBridge.h:69
llvm::orc::shared::makeMethodWrapperHandler
MethodWrapperHandler< RetT, ClassT, ArgTs... > makeMethodWrapperHandler(RetT(ClassT::*Method)(ArgTs...))
Create a MethodWrapperHandler object from the given method pointer.
Definition:WrapperFunctionUtils.h:619
llvm::orc::MemProt::Exec
@ Exec
llvm::orc::ExecutorAddrDiff
uint64_t ExecutorAddrDiff
Definition:ExecutorAddress.h:31
llvm::orc::toSysMemoryProtectionFlags
sys::Memory::ProtectionFlags toSysMemoryProtectionFlags(MemProt MP)
Convert a MemProt value to a corresponding sys::Memory::ProtectionFlags value.
Definition:MemoryFlags.h:44
llvm::sampleprof::Base
@ Base
Definition:Discriminator.h:58
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition:Error.cpp:98
llvm::formatv
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Definition:FormatVariadic.h:252
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition:Error.h:438
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition:Error.cpp:111
llvm::orc::shared::CWrapperFunctionResult
Definition:WrapperFunctionUtils.h:33
llvm::orc::tpctypes::FinalizeRequest
Definition:TargetProcessControlTypes.h:56
llvm::orc::tpctypes::FinalizeRequest::Segments
std::vector< SegFinalizeRequest > Segments
Definition:TargetProcessControlTypes.h:57
llvm::orc::tpctypes::FinalizeRequest::Actions
shared::AllocActions Actions
Definition:TargetProcessControlTypes.h:58

Generated on Fri Jul 18 2025 11:28:08 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp