1 //===--- JITLinkMemoryManager.cpp - JITLinkMemoryManager implementation ---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
11 #include "llvm/Support/Process.h"
16 JITLinkMemoryManager::~JITLinkMemoryManager() = default;
17 JITLinkMemoryManager::Allocation::~Allocation() = default;
19 Expected
<std::unique_ptr
<JITLinkMemoryManager::Allocation
>>
20 InProcessMemoryManager::allocate(const SegmentsRequestMap
&Request
) {
22 using AllocationMap
= DenseMap
<unsigned, sys::MemoryBlock
>;
24 // Local class for allocation.
25 class IPMMAlloc
: public Allocation
{
27 IPMMAlloc(AllocationMap SegBlocks
) : SegBlocks(std::move(SegBlocks
)) {}
28 MutableArrayRef
<char> getWorkingMemory(ProtectionFlags Seg
) override
{
29 assert(SegBlocks
.count(Seg
) && "No allocation for segment");
30 return {static_cast<char *>(SegBlocks
[Seg
].base()),
31 SegBlocks
[Seg
].allocatedSize()};
33 JITTargetAddress
getTargetMemory(ProtectionFlags Seg
) override
{
34 assert(SegBlocks
.count(Seg
) && "No allocation for segment");
35 return reinterpret_cast<JITTargetAddress
>(SegBlocks
[Seg
].base());
37 void finalizeAsync(FinalizeContinuation OnFinalize
) override
{
38 OnFinalize(applyProtections());
40 Error
deallocate() override
{
41 for (auto &KV
: SegBlocks
)
42 if (auto EC
= sys::Memory::releaseMappedMemory(KV
.second
))
43 return errorCodeToError(EC
);
44 return Error::success();
48 Error
applyProtections() {
49 for (auto &KV
: SegBlocks
) {
50 auto &Prot
= KV
.first
;
51 auto &Block
= KV
.second
;
52 if (auto EC
= sys::Memory::protectMappedMemory(Block
, Prot
))
53 return errorCodeToError(EC
);
54 if (Prot
& sys::Memory::MF_EXEC
)
55 sys::Memory::InvalidateInstructionCache(Block
.base(),
56 Block
.allocatedSize());
58 return Error::success();
61 AllocationMap SegBlocks
;
65 const sys::Memory::ProtectionFlags ReadWrite
=
66 static_cast<sys::Memory::ProtectionFlags
>(sys::Memory::MF_READ
|
67 sys::Memory::MF_WRITE
);
69 for (auto &KV
: Request
) {
70 auto &Seg
= KV
.second
;
72 if (Seg
.getContentAlignment() > sys::Process::getPageSizeEstimate())
73 return make_error
<StringError
>("Cannot request higher than page "
75 inconvertibleErrorCode());
77 if (sys::Process::getPageSizeEstimate() % Seg
.getContentAlignment() != 0)
78 return make_error
<StringError
>("Page size is not a multiple of "
80 inconvertibleErrorCode());
82 uint64_t ZeroFillStart
=
83 alignTo(Seg
.getContentSize(), Seg
.getZeroFillAlignment());
84 uint64_t SegmentSize
= ZeroFillStart
+ Seg
.getZeroFillSize();
88 sys::Memory::allocateMappedMemory(SegmentSize
, nullptr, ReadWrite
, EC
);
91 return errorCodeToError(EC
);
93 // Zero out the zero-fill memory.
94 memset(static_cast<char *>(SegMem
.base()) + ZeroFillStart
, 0,
95 Seg
.getZeroFillSize());
97 // Record the block for this segment.
98 Blocks
[KV
.first
] = std::move(SegMem
);
100 return std::unique_ptr
<InProcessMemoryManager::Allocation
>(
101 new IPMMAlloc(std::move(Blocks
)));
104 } // end namespace jitlink
105 } // end namespace llvm