1cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- C++ -*-==//
22d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//
32d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//                     The LLVM Compiler Infrastructure
42d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//
52d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// This file is distributed under the University of Illinois Open Source
62d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor// License. See LICENSE.TXT for details.
72d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//
82d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//===----------------------------------------------------------------------===//
92d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//
10cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor// This file implements the section-based memory manager used by the MCJIT
11cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor// execution engine and RuntimeDyld
122d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//
132d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor//===----------------------------------------------------------------------===//
142d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
152d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor#include "llvm/Config/config.h"
16927ba6a0b36b8219955a657545fcb1c863734993Andrew Kaylor#include "llvm/ExecutionEngine/SectionMemoryManager.h"
17a25ad19a23c20a235e8c8dc7d863324a64ef045eAmara Emerson#include "llvm/Support/MathExtras.h"
18f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/Support/Process.h"
192d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
202d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylornamespace llvm {
212d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
222d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kayloruint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
236eb43d295625cd2ff314c59b49d4fd11f3348cadFilip Pizlo                                                   unsigned Alignment,
246eb43d295625cd2ff314c59b49d4fd11f3348cadFilip Pizlo                                                   unsigned SectionID,
256eb43d295625cd2ff314c59b49d4fd11f3348cadFilip Pizlo                                                   StringRef SectionName,
266eb43d295625cd2ff314c59b49d4fd11f3348cadFilip Pizlo                                                   bool IsReadOnly) {
27cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  if (IsReadOnly)
28cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor    return allocateSection(RODataMem, Size, Alignment);
29cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  return allocateSection(RWDataMem, Size, Alignment);
302d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor}
312d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
322d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kayloruint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size,
33cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                                   unsigned Alignment,
346eb43d295625cd2ff314c59b49d4fd11f3348cadFilip Pizlo                                                   unsigned SectionID,
356eb43d295625cd2ff314c59b49d4fd11f3348cadFilip Pizlo                                                   StringRef SectionName) {
36cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  return allocateSection(CodeMem, Size, Alignment);
37cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor}
38cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
39cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kayloruint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup,
40cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                               uintptr_t Size,
41cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                               unsigned Alignment) {
422d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  if (!Alignment)
432d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor    Alignment = 16;
44cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
45cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power of two.");
46cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
47cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1)/Alignment + 1);
482d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  uintptr_t Addr = 0;
49cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
50cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // Look in the list of free memory regions and use a block there if one
512d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  // is available.
52f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  for (FreeMemBlock &FreeMB : MemGroup.FreeMem) {
53f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    if (FreeMB.Free.size() >= RequiredSize) {
54f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      Addr = (uintptr_t)FreeMB.Free.base();
55f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      uintptr_t EndOfBlock = Addr + FreeMB.Free.size();
562d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor      // Align the address.
572d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor      Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
58f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
59f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      if (FreeMB.PendingPrefixIndex == (unsigned)-1) {
60f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        // The part of the block we're giving out to the user is now pending
61f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        MemGroup.PendingMem.push_back(sys::MemoryBlock((void *)Addr, Size));
62f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
63f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        // Remember this pending block, such that future allocations can just
64f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        // modify it rather than creating a new one
65f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        FreeMB.PendingPrefixIndex = MemGroup.PendingMem.size() - 1;
66f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      } else {
67f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        sys::MemoryBlock &PendingMB = MemGroup.PendingMem[FreeMB.PendingPrefixIndex];
68f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        PendingMB = sys::MemoryBlock(PendingMB.base(), Addr + Size - (uintptr_t)PendingMB.base());
69f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      }
70f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
71f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      // Remember how much free space is now left in this block
72f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      FreeMB.Free = sys::MemoryBlock((void *)(Addr + Size), EndOfBlock - Addr - Size);
732d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor      return (uint8_t*)Addr;
742d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor    }
752d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  }
762d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
772d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  // No pre-allocated free block was large enough. Allocate a new memory region.
78cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // Note that all sections get allocated as read-write.  The permissions will
79cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // be updated later based on memory group.
80cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  //
81cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // FIXME: It would be useful to define a default allocation size (or add
82cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // it as a constructor parameter) to minimize the number of allocations.
83927ba6a0b36b8219955a657545fcb1c863734993Andrew Kaylor  //
84cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // FIXME: Initialize the Near member for each memory group to avoid
85cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // interleaving.
86c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  std::error_code ec;
87cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize,
88cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                                          &MemGroup.Near,
89cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                                          sys::Memory::MF_READ |
90cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                                            sys::Memory::MF_WRITE,
91cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                                          ec);
92cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  if (ec) {
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // FIXME: Add error propagation to the interface.
94dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
95cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  }
962d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
97cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // Save this address as the basis for our next request
98cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  MemGroup.Near = MB;
99cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
100f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  // Remember that we allocated this memory
101cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  MemGroup.AllocatedMem.push_back(MB);
1022d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  Addr = (uintptr_t)MB.base();
1032d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  uintptr_t EndOfBlock = Addr + MB.size();
104cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
1052d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  // Align the address.
1062d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
107cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
108f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  // The part of the block we're giving out to the user is now pending
109f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  MemGroup.PendingMem.push_back(sys::MemoryBlock((void *)Addr, Size));
110f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
111cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // The allocateMappedMemory may allocate much more memory than we need. In
112cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // this case, we store the unused memory as a free memory block.
1132d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  unsigned FreeSize = EndOfBlock-Addr-Size;
114f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  if (FreeSize > 16) {
115f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    FreeMemBlock FreeMB;
116f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    FreeMB.Free = sys::MemoryBlock((void*)(Addr + Size), FreeSize);
117f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    FreeMB.PendingPrefixIndex = (unsigned)-1;
118f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    MemGroup.FreeMem.push_back(FreeMB);
119f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  }
1202d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
1212d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  // Return aligned address
1222d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor  return (uint8_t*)Addr;
1232d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor}
1242d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
125abb38fe8dec11b1ea7535f84fac8ad0f0af70addDavid Tweedbool SectionMemoryManager::finalizeMemory(std::string *ErrMsg)
126cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor{
127cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // FIXME: Should in-progress permissions be reverted if an error occurs?
128c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  std::error_code ec;
129cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
130cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // Make code memory executable.
131cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  ec = applyMemoryGroupPermissions(CodeMem,
132cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                   sys::Memory::MF_READ | sys::Memory::MF_EXEC);
133cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  if (ec) {
134cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor    if (ErrMsg) {
135cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor      *ErrMsg = ec.message();
136cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor    }
137cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor    return true;
138cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  }
139cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
140cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // Make read-only data memory read-only.
141cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  ec = applyMemoryGroupPermissions(RODataMem,
142cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor                                   sys::Memory::MF_READ | sys::Memory::MF_EXEC);
143cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  if (ec) {
144cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor    if (ErrMsg) {
145cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor      *ErrMsg = ec.message();
146cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor    }
147cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor    return true;
148cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  }
149cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
150cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  // Read-write data memory already has the correct permissions
151cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
152034f4be273f0ec629da4bc8369578fc195f3212fAndrew Kaylor  // Some platforms with separate data cache and instruction cache require
153034f4be273f0ec629da4bc8369578fc195f3212fAndrew Kaylor  // explicit cache flush, otherwise JIT code manipulations (like resolved
154034f4be273f0ec629da4bc8369578fc195f3212fAndrew Kaylor  // relocations) will get to the data cache but not to the instruction cache.
155034f4be273f0ec629da4bc8369578fc195f3212fAndrew Kaylor  invalidateInstructionCache();
156034f4be273f0ec629da4bc8369578fc195f3212fAndrew Kaylor
157cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  return false;
158cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor}
159cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
160f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarstatic sys::MemoryBlock trimBlockToPageSize(sys::MemoryBlock M) {
161f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  static const size_t PageSize = sys::Process::getPageSize();
162f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
163f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  size_t StartOverlap =
164f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      (PageSize - ((uintptr_t)M.base() % PageSize)) % PageSize;
165f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
166f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  size_t TrimmedSize = M.size();
167f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  TrimmedSize -= StartOverlap;
168f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  TrimmedSize -= TrimmedSize % PageSize;
169f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
170f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  sys::MemoryBlock Trimmed((void *)((uintptr_t)M.base() + StartOverlap), TrimmedSize);
171f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
172f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  assert(((uintptr_t)Trimmed.base() % PageSize) == 0);
173f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  assert((Trimmed.size() % PageSize) == 0);
174f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  assert(M.base() <= Trimmed.base() && Trimmed.size() <= M.size());
175f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
176f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  return Trimmed;
177f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
178f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
179f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
180c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code
181c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesSectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup,
182c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                                                  unsigned Permissions) {
183f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  for (sys::MemoryBlock &MB : MemGroup.PendingMem)
184f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    if (std::error_code EC = sys::Memory::protectMappedMemory(MB, Permissions))
185f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      return EC;
186f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
187f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  MemGroup.PendingMem.clear();
188f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
189f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  // Now go through free blocks and trim any of them that don't span the entire
190f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  // page because one of the pending blocks may have overlapped it.
191f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  for (FreeMemBlock &FreeMB : MemGroup.FreeMem) {
192f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    FreeMB.Free = trimBlockToPageSize(FreeMB.Free);
193f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // We cleared the PendingMem list, so all these pointers are now invalid
194f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    FreeMB.PendingPrefixIndex = (unsigned)-1;
195cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor  }
196cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
197f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  // Remove all blocks which are now empty
198f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  MemGroup.FreeMem.erase(
199f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      std::remove_if(MemGroup.FreeMem.begin(), MemGroup.FreeMem.end(),
200f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                     [](FreeMemBlock &FreeMB) { return FreeMB.Free.size() == 0; }),
201f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      MemGroup.FreeMem.end());
202f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
203c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  return std::error_code();
204cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor}
205cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
2062d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylorvoid SectionMemoryManager::invalidateInstructionCache() {
207f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  for (sys::MemoryBlock &Block : CodeMem.PendingMem)
208f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    sys::Memory::InvalidateInstructionCache(Block.base(), Block.size());
209cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor}
210cc7773bdcbecf893cb9442a77cdf5e41f2af4256Andrew Kaylor
2112d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew KaylorSectionMemoryManager::~SectionMemoryManager() {
212f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  for (MemoryGroup *Group : {&CodeMem, &RWDataMem, &RODataMem}) {
213f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    for (sys::MemoryBlock &Block : Group->AllocatedMem)
214f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      sys::Memory::releaseMappedMemory(Block);
215f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  }
2162d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor}
2172d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor
2182d6d585c85ce8c56461f17b7b49fff24eed7b8fbAndrew Kaylor} // namespace llvm
219