LLVM  10.0.0svn
JITLinkMemoryManager.cpp
Go to the documentation of this file.
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 
11 #include "llvm/Support/Process.h"
12 
13 namespace llvm {
14 namespace jitlink {
15 
18 
19 Expected<std::unique_ptr<JITLinkMemoryManager::Allocation>>
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  if (SegBlocks.empty())
42  return Error::success();
43  void *SlabStart = SegBlocks.begin()->second.base();
44  char *SlabEnd = (char *)SlabStart;
45  for (auto &KV : SegBlocks) {
46  SlabStart = std::min(SlabStart, KV.second.base());
47  SlabEnd = std::max(SlabEnd, (char *)(KV.second.base()) +
48  KV.second.allocatedSize());
49  }
50  size_t SlabSize = SlabEnd - (char *)SlabStart;
51  assert((SlabSize % sys::Process::getPageSizeEstimate()) == 0 &&
52  "Slab size is not a multiple of page size");
53  sys::MemoryBlock Slab(SlabStart, SlabSize);
54  if (auto EC = sys::Memory::releaseMappedMemory(Slab))
55  return errorCodeToError(EC);
56  return Error::success();
57  }
58 
59  private:
60  Error applyProtections() {
61  for (auto &KV : SegBlocks) {
62  auto &Prot = KV.first;
63  auto &Block = KV.second;
64  if (auto EC = sys::Memory::protectMappedMemory(Block, Prot))
65  return errorCodeToError(EC);
66  if (Prot & sys::Memory::MF_EXEC)
68  Block.allocatedSize());
69  }
70  return Error::success();
71  }
72 
73  AllocationMap SegBlocks;
74  };
75 
77  return make_error<StringError>("Page size is not a power of 2",
79 
80  AllocationMap Blocks;
81  const sys::Memory::ProtectionFlags ReadWrite =
84 
85  // Compute the total number of pages to allocate.
86  size_t TotalSize = 0;
87  for (auto &KV : Request) {
88  const auto &Seg = KV.second;
89 
90  if (Seg.getAlignment() > sys::Process::getPageSizeEstimate())
91  return make_error<StringError>("Cannot request higher than page "
92  "alignment",
94 
95  TotalSize = alignTo(TotalSize, sys::Process::getPageSizeEstimate());
96  TotalSize += Seg.getContentSize();
97  TotalSize += Seg.getZeroFillSize();
98  }
99 
100  // Allocate one slab to cover all the segments.
101  std::error_code EC;
102  auto SlabRemaining =
103  sys::Memory::allocateMappedMemory(TotalSize, nullptr, ReadWrite, EC);
104 
105  if (EC)
106  return errorCodeToError(EC);
107 
108  // Allocate segment memory from the slab.
109  for (auto &KV : Request) {
110 
111  const auto &Seg = KV.second;
112 
113  uint64_t SegmentSize = alignTo(Seg.getContentSize() + Seg.getZeroFillSize(),
115 
116  sys::MemoryBlock SegMem(SlabRemaining.base(), SegmentSize);
117  SlabRemaining = sys::MemoryBlock((char *)SlabRemaining.base() + SegmentSize,
118  SegmentSize);
119 
120  // Zero out the zero-fill memory.
121  memset(static_cast<char *>(SegMem.base()) + Seg.getContentSize(), 0,
122  Seg.getZeroFillSize());
123 
124  // Record the block for this segment.
125  Blocks[KV.first] = std::move(SegMem);
126  }
127  return std::unique_ptr<InProcessMemoryManager::Allocation>(
128  new IPMMAlloc(std::move(Blocks)));
129 }
130 
131 } // end namespace jitlink
132 } // end namespace llvm
This class represents lattice values for constants.
Definition: AllocatorList.h:23
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 unsigned getPageSizeEstimate()
Get the process&#39;s estimated page size.
Definition: Process.h:56
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:41
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:290
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:87
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:470
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:390
This class encapsulates the notion of a memory block which has an address and a size.
Definition: Memory.h:32
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:163
Provides a library for accessing information about this process and other processes on the operating ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77
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...