16#if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
36 return PageSize.takeError();
37 return std::make_unique<InProcessMemoryMapper>(*PageSize);
50 std::lock_guard<std::mutex> Lock(
Mutex);
51 Reservations[MB.base()].Size = MB.allocatedSize();
59 return Addr.toPtr<
char *>();
70 auto Size = Segment.ContentSize + Segment.ZeroFillSize;
78 std::memset((
Base + Segment.ContentSize).toPtr<
void *>(), 0,
79 Segment.ZeroFillSize);
91 if (!DeinitializeActions)
92 return OnInitialized(DeinitializeActions.takeError());
95 std::lock_guard<std::mutex> Lock(
Mutex);
98 Allocations[MinAddr].Size = MaxAddr - MinAddr;
99 Allocations[MinAddr].DeinitializationActions =
100 std::move(*DeinitializeActions);
101 Reservations[AI.
MappingBase.
toPtr<
void *>()].Allocations.push_back(MinAddr);
104 OnInitialized(MinAddr);
113 std::lock_guard<std::mutex> Lock(
Mutex);
118 Allocations[
Base].DeinitializationActions)) {
119 AllErr =
joinErrors(std::move(AllErr), std::move(Err));
134 OnDeinitialized(std::move(AllErr));
141 for (
auto Base : Bases) {
142 std::vector<ExecutorAddr> AllocAddrs;
145 std::lock_guard<std::mutex> Lock(
Mutex);
146 auto &R = Reservations[
Base.toPtr<
void *>()];
148 AllocAddrs.swap(R.Allocations);
152 std::promise<MSVCPError>
P;
153 auto F =
P.get_future();
167 std::lock_guard<std::mutex> Lock(
Mutex);
168 Reservations.
erase(
Base.toPtr<
void *>());
171 OnReleased(std::move(Err));
175 std::vector<ExecutorAddr> ReservationAddrs;
177 std::lock_guard<std::mutex> Lock(
Mutex);
179 ReservationAddrs.reserve(Reservations.
size());
180 for (
const auto &R : Reservations) {
185 std::promise<MSVCPError>
P;
186 auto F =
P.get_future();
187 release(ReservationAddrs, [&](
Error Err) {
P.set_value(std::move(Err)); });
196#if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32)
197 llvm_unreachable(
"SharedMemoryMapper is not supported on this platform yet");
203#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
206 return PageSize.takeError();
208 return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize);
210 return make_error<StringError>(
211 "SharedMemoryMapper is not supported on this platform yet",
218#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
223 [
this, NumBytes, OnReserved = std::move(OnReserved)](
224 Error SerializationErr,
226 if (SerializationErr) {
228 return OnReserved(std::move(SerializationErr));
232 return OnReserved(
Result.takeError());
235 std::string SharedMemoryName;
236 std::tie(RemoteAddr, SharedMemoryName) = std::move(*
Result);
238 void *LocalAddr =
nullptr;
240#if defined(LLVM_ON_UNIX)
242 int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700);
243 if (SharedMemoryFile < 0) {
245 std::error_code(errno, std::generic_category())));
249 shm_unlink(SharedMemoryName.c_str());
251 LocalAddr = mmap(
nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
252 SharedMemoryFile, 0);
253 if (LocalAddr == MAP_FAILED) {
255 std::error_code(errno, std::generic_category())));
258 close(SharedMemoryFile);
262 std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
263 SharedMemoryName.end());
264 HANDLE SharedMemoryFile = OpenFileMappingW(
265 FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str());
266 if (!SharedMemoryFile)
270 MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
272 CloseHandle(SharedMemoryFile);
276 CloseHandle(SharedMemoryFile);
280 std::lock_guard<std::mutex> Lock(
Mutex);
281 Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}});
289 OnReserved(make_error<StringError>(
290 "SharedMemoryMapper is not supported on this platform yet",
296 auto R = Reservations.upper_bound(
Addr);
297 assert(R != Reservations.begin() &&
"Attempt to prepare unreserved range");
302 return static_cast<char *
>(R->second.LocalAddr) +
Offset;
307 auto Reservation = Reservations.upper_bound(AI.
MappingBase);
308 assert(Reservation != Reservations.begin() &&
"Attempt to initialize unreserved range");
311 auto AllocationOffset = AI.
MappingBase - Reservation->first;
320 char *
Base =
static_cast<char *
>(Reservation->second.LocalAddr) +
321 AllocationOffset + Segment.Offset;
322 std::memset(
Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
325 SegReq.
RAG = {Segment.AG.getMemProt(), Segment.AG.getMemLifetimePolicy() ==
328 SegReq.
Size = Segment.ContentSize + Segment.ZeroFillSize;
336 [OnInitialized = std::move(OnInitialized)](
338 if (SerializationErr) {
340 return OnInitialized(std::move(SerializationErr));
343 OnInitialized(std::move(
Result));
345 SAs.
Instance, Reservation->first, std::move(FR));
354 [OnDeinitialized = std::move(OnDeinitialized)](
Error SerializationErr,
356 if (SerializationErr) {
358 return OnDeinitialized(std::move(SerializationErr));
361 OnDeinitialized(std::move(
Result));
368#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
372 std::lock_guard<std::mutex> Lock(
Mutex);
374 for (
auto Base : Bases) {
376#if defined(LLVM_ON_UNIX)
378 if (munmap(Reservations[
Base].LocalAddr, Reservations[
Base].
Size) != 0)
380 errno, std::generic_category())));
384 if (!UnmapViewOfFile(Reservations[
Base].LocalAddr))
390 Reservations.erase(
Base);
397 [OnReleased = std::move(OnReleased),
399 if (SerializationErr) {
402 joinErrors(std::move(Err), std::move(SerializationErr)));
409 OnReleased(make_error<StringError>(
410 "SharedMemoryMapper is not supported on this platform yet",
416 std::lock_guard<std::mutex> Lock(
Mutex);
417 for (
const auto &R : Reservations) {
419#if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
421 munmap(R.second.LocalAddr, R.second.Size);
425 UnmapViewOfFile(R.second.LocalAddr);
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool erase(const KeyT &Val)
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.
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.
ExecutorProcessControl supports interaction with a JIT target process.
void callSPSWrapperAsync(RunPolicyT &&Runner, ExecutorAddr WrapperFnAddr, SendResultT &&SendResult, const ArgTs &...Args)
Run a wrapper function using SPS to serialize the arguments and deserialize the results.
void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override
Ensures executor memory is synchronized with working copy memory, sends functions to be called after ...
void reserve(size_t NumBytes, OnReservedFunction OnReserved) override
Reserves address space in executor process.
InProcessMemoryMapper(size_t PageSize)
~InProcessMemoryMapper() override
void deinitialize(ArrayRef< ExecutorAddr > Allocations, OnDeinitializedFunction OnDeInitialized) override
Runs previously specified deinitialization actions Executor addresses returned by initialize should b...
static Expected< std::unique_ptr< InProcessMemoryMapper > > Create()
char * prepare(ExecutorAddr Addr, size_t ContentSize) override
Provides working memory.
void release(ArrayRef< ExecutorAddr > Reservations, OnReleasedFunction OnRelease) override
Release address space acquired through reserve()
static Expected< std::unique_ptr< SharedMemoryMapper > > Create(ExecutorProcessControl &EPC, SymbolAddrs SAs)
void reserve(size_t NumBytes, OnReservedFunction OnReserved) override
Reserves address space in executor process.
void deinitialize(ArrayRef< ExecutorAddr > Allocations, OnDeinitializedFunction OnDeInitialized) override
Runs previously specified deinitialization actions Executor addresses returned by initialize should b...
~SharedMemoryMapper() override
void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override
Ensures executor memory is synchronized with working copy memory, sends functions to be called after ...
char * prepare(ExecutorAddr Addr, size_t ContentSize) override
Provides working memory.
void release(ArrayRef< ExecutorAddr > Reservations, OnReleasedFunction OnRelease) override
Release address space acquired through reserve()
SharedMemoryMapper(ExecutorProcessControl &EPC, SymbolAddrs SAs, size_t PageSize)
This class encapsulates the notion of a memory block which has an address and a size.
static std::error_code releaseMappedMemory(MemoryBlock &Block)
This method releases a block of memory that was allocated with the allocateMappedMemory method.
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....
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...
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.
static Expected< unsigned > getPageSize()
Get the process's page size.
unique_function is a type-erasing functor similar to std::function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
shared::SPSExpected< shared::SPSExecutorAddr >(shared::SPSExecutorAddr, shared::SPSExecutorAddr, shared::SPSSharedMemoryFinalizeRequest) SPSExecutorSharedMemoryMapperServiceInitializeSignature
shared::SPSError(shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSExecutorSharedMemoryMapperServiceReleaseSignature
shared::SPSExpected< shared::SPSTuple< shared::SPSExecutorAddr, shared::SPSString > >(shared::SPSExecutorAddr, uint64_t) SPSExecutorSharedMemoryMapperServiceReserveSignature
shared::SPSError(shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSExecutorSharedMemoryMapperServiceDeinitializeSignature
Error runDeallocActions(ArrayRef< WrapperFunctionCall > DAs)
Run deallocation actions.
Expected< std::vector< WrapperFunctionCall > > runFinalizeActions(AllocActions &AAs)
Run finalize actions.
@ Finalize
Finalize memory should be allocated by the allocator, and then be overwritten and deallocated after a...
sys::Memory::ProtectionFlags toSysMemoryProtectionFlags(MemProt MP)
Convert a MemProt value to a corresponding sys::Memory::ProtectionFlags value.
This is an optimization pass for GlobalISel generic memory operations.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto reverse(ContainerTy &&C)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
std::error_code mapWindowsError(unsigned EV)
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
ExecutorAddr Deinitialize
std::vector< SharedMemorySegFinalizeRequest > Segments
shared::AllocActions Actions