MapperJITLinkMemoryManager.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. //=== MapperJITLinkMemoryManager.cpp - Memory management with MemoryMapper ===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
  9. #include "llvm/ADT/STLExtras.h"
  10. #include "llvm/ExecutionEngine/JITLink/JITLink.h"
  11. #include "llvm/Support/Process.h"
  12. using namespace llvm::jitlink;
  13. namespace llvm {
  14. namespace orc {
  15. class MapperJITLinkMemoryManager::InFlightAlloc
  16. : public JITLinkMemoryManager::InFlightAlloc {
  17. public:
  18. InFlightAlloc(MapperJITLinkMemoryManager &Parent, LinkGraph &G,
  19. ExecutorAddr AllocAddr,
  20. std::vector<MemoryMapper::AllocInfo::SegInfo> Segs)
  21. : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
  22. void finalize(OnFinalizedFunction OnFinalize) override {
  23. MemoryMapper::AllocInfo AI;
  24. AI.MappingBase = AllocAddr;
  25. std::swap(AI.Segments, Segs);
  26. std::swap(AI.Actions, G.allocActions());
  27. Parent.Mapper->initialize(AI, [OnFinalize = std::move(OnFinalize)](
  28. Expected<ExecutorAddr> Result) mutable {
  29. if (!Result) {
  30. OnFinalize(Result.takeError());
  31. return;
  32. }
  33. OnFinalize(FinalizedAlloc(*Result));
  34. });
  35. }
  36. void abandon(OnAbandonedFunction OnFinalize) override {
  37. Parent.Mapper->release({AllocAddr}, std::move(OnFinalize));
  38. }
  39. private:
  40. MapperJITLinkMemoryManager &Parent;
  41. LinkGraph &G;
  42. ExecutorAddr AllocAddr;
  43. std::vector<MemoryMapper::AllocInfo::SegInfo> Segs;
  44. };
  45. MapperJITLinkMemoryManager::MapperJITLinkMemoryManager(
  46. size_t ReservationGranularity, std::unique_ptr<MemoryMapper> Mapper)
  47. : ReservationUnits(ReservationGranularity), AvailableMemory(AMAllocator),
  48. Mapper(std::move(Mapper)) {}
  49. void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
  50. OnAllocatedFunction OnAllocated) {
  51. BasicLayout BL(G);
  52. // find required address space
  53. auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(Mapper->getPageSize());
  54. if (!SegsSizes) {
  55. OnAllocated(SegsSizes.takeError());
  56. return;
  57. }
  58. auto TotalSize = SegsSizes->total();
  59. auto CompleteAllocation = [this, &G, BL = std::move(BL),
  60. OnAllocated = std::move(OnAllocated)](
  61. Expected<ExecutorAddrRange> Result) mutable {
  62. if (!Result) {
  63. Mutex.unlock();
  64. return OnAllocated(Result.takeError());
  65. }
  66. auto NextSegAddr = Result->Start;
  67. std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
  68. for (auto &KV : BL.segments()) {
  69. auto &AG = KV.first;
  70. auto &Seg = KV.second;
  71. auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
  72. Seg.Addr = NextSegAddr;
  73. Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
  74. NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
  75. MemoryMapper::AllocInfo::SegInfo SI;
  76. SI.Offset = Seg.Addr - Result->Start;
  77. SI.ContentSize = Seg.ContentSize;
  78. SI.ZeroFillSize = Seg.ZeroFillSize;
  79. SI.AG = AG;
  80. SI.WorkingMem = Seg.WorkingMem;
  81. SegInfos.push_back(SI);
  82. }
  83. UsedMemory.insert({Result->Start, NextSegAddr - Result->Start});
  84. if (NextSegAddr < Result->End) {
  85. // Save the remaining memory for reuse in next allocation(s)
  86. AvailableMemory.insert(NextSegAddr, Result->End - 1, true);
  87. }
  88. Mutex.unlock();
  89. if (auto Err = BL.apply()) {
  90. OnAllocated(std::move(Err));
  91. return;
  92. }
  93. OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
  94. std::move(SegInfos)));
  95. };
  96. Mutex.lock();
  97. // find an already reserved range that is large enough
  98. ExecutorAddrRange SelectedRange{};
  99. for (AvailableMemoryMap::iterator It = AvailableMemory.begin();
  100. It != AvailableMemory.end(); It++) {
  101. if (It.stop() - It.start() + 1 >= TotalSize) {
  102. SelectedRange = ExecutorAddrRange(It.start(), It.stop() + 1);
  103. It.erase();
  104. break;
  105. }
  106. }
  107. if (SelectedRange.empty()) { // no already reserved range was found
  108. auto TotalAllocation = alignTo(TotalSize, ReservationUnits);
  109. Mapper->reserve(TotalAllocation, std::move(CompleteAllocation));
  110. } else {
  111. CompleteAllocation(SelectedRange);
  112. }
  113. }
  114. void MapperJITLinkMemoryManager::deallocate(
  115. std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
  116. std::vector<ExecutorAddr> Bases;
  117. Bases.reserve(Allocs.size());
  118. for (auto &FA : Allocs) {
  119. ExecutorAddr Addr = FA.getAddress();
  120. Bases.push_back(Addr);
  121. }
  122. Mapper->deinitialize(Bases, [this, Allocs = std::move(Allocs),
  123. OnDeallocated = std::move(OnDeallocated)](
  124. llvm::Error Err) mutable {
  125. // TODO: How should we treat memory that we fail to deinitialize?
  126. // We're currently bailing out and treating it as "burned" -- should we
  127. // require that a failure to deinitialize still reset the memory so that
  128. // we can reclaim it?
  129. if (Err) {
  130. for (auto &FA : Allocs)
  131. FA.release();
  132. OnDeallocated(std::move(Err));
  133. return;
  134. }
  135. {
  136. std::lock_guard<std::mutex> Lock(Mutex);
  137. for (auto &FA : Allocs) {
  138. ExecutorAddr Addr = FA.getAddress();
  139. ExecutorAddrDiff Size = UsedMemory[Addr];
  140. UsedMemory.erase(Addr);
  141. AvailableMemory.insert(Addr, Addr + Size - 1, true);
  142. FA.release();
  143. }
  144. }
  145. OnDeallocated(Error::success());
  146. });
  147. }
  148. } // end namespace orc
  149. } // end namespace llvm