]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
Fix a memory leak in if_delgroups() introduced in r334118.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / ExecutionEngine / JITLink / JITLinkMemoryManager.cpp
1 //===--- JITLinkMemoryManager.cpp - JITLinkMemoryManager implementation ---===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
11 #include "llvm/Support/Process.h"
12
13 namespace llvm {
14 namespace jitlink {
15
16 JITLinkMemoryManager::~JITLinkMemoryManager() = default;
17 JITLinkMemoryManager::Allocation::~Allocation() = default;
18
19 Expected<std::unique_ptr<JITLinkMemoryManager::Allocation>>
20 InProcessMemoryManager::allocate(const SegmentsRequestMap &Request) {
21
22   using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>;
23
24   // Local class for allocation.
25   class IPMMAlloc : public Allocation {
26   public:
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()};
32     }
33     JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
34       assert(SegBlocks.count(Seg) && "No allocation for segment");
35       return reinterpret_cast<JITTargetAddress>(SegBlocks[Seg].base());
36     }
37     void finalizeAsync(FinalizeContinuation OnFinalize) override {
38       OnFinalize(applyProtections());
39     }
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();
45     }
46
47   private:
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());
57       }
58       return Error::success();
59     }
60
61     AllocationMap SegBlocks;
62   };
63
64   AllocationMap Blocks;
65   const sys::Memory::ProtectionFlags ReadWrite =
66       static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
67                                                 sys::Memory::MF_WRITE);
68
69   for (auto &KV : Request) {
70     auto &Seg = KV.second;
71
72     if (Seg.getContentAlignment() > sys::Process::getPageSizeEstimate())
73       return make_error<StringError>("Cannot request higher than page "
74                                      "alignment",
75                                      inconvertibleErrorCode());
76
77     if (sys::Process::getPageSizeEstimate() % Seg.getContentAlignment() != 0)
78       return make_error<StringError>("Page size is not a multiple of "
79                                      "alignment",
80                                      inconvertibleErrorCode());
81
82     uint64_t ZeroFillStart =
83         alignTo(Seg.getContentSize(), Seg.getZeroFillAlignment());
84     uint64_t SegmentSize = ZeroFillStart + Seg.getZeroFillSize();
85
86     std::error_code EC;
87     auto SegMem =
88         sys::Memory::allocateMappedMemory(SegmentSize, nullptr, ReadWrite, EC);
89
90     if (EC)
91       return errorCodeToError(EC);
92
93     // Zero out the zero-fill memory.
94     memset(static_cast<char *>(SegMem.base()) + ZeroFillStart, 0,
95            Seg.getZeroFillSize());
96
97     // Record the block for this segment.
98     Blocks[KV.first] = std::move(SegMem);
99   }
100   return std::unique_ptr<InProcessMemoryManager::Allocation>(
101       new IPMMAlloc(std::move(Blocks)));
102 }
103
104 } // end namespace jitlink
105 } // end namespace llvm