EPCGenericJITLinkMemoryManager.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. //===---- EPCGenericJITLinkMemoryManager.cpp -- Mem management via EPC ----===//
  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/EPCGenericJITLinkMemoryManager.h"
  9. #include "llvm/ExecutionEngine/JITLink/JITLink.h"
  10. #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
  11. #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
  12. #include <limits>
  13. using namespace llvm::jitlink;
  14. namespace llvm {
  15. namespace orc {
  16. class EPCGenericJITLinkMemoryManager::InFlightAlloc
  17. : public jitlink::JITLinkMemoryManager::InFlightAlloc {
  18. public:
  19. // FIXME: The C++98 initializer is an attempt to work around compile failures
  20. // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
  21. // We should be able to switch this back to member initialization once that
  22. // issue is fixed.
  23. struct SegInfo {
  24. SegInfo() : WorkingMem(nullptr), ContentSize(0), ZeroFillSize(0) {}
  25. char *WorkingMem;
  26. ExecutorAddr Addr;
  27. uint64_t ContentSize;
  28. uint64_t ZeroFillSize;
  29. };
  30. using SegInfoMap = AllocGroupSmallMap<SegInfo>;
  31. InFlightAlloc(EPCGenericJITLinkMemoryManager &Parent, LinkGraph &G,
  32. ExecutorAddr AllocAddr, SegInfoMap Segs)
  33. : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
  34. void finalize(OnFinalizedFunction OnFinalize) override {
  35. tpctypes::FinalizeRequest FR;
  36. for (auto &KV : Segs) {
  37. assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
  38. FR.Segments.push_back(tpctypes::SegFinalizeRequest{
  39. tpctypes::toWireProtectionFlags(
  40. toSysMemoryProtectionFlags(KV.first.getMemProt())),
  41. KV.second.Addr,
  42. alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
  43. Parent.EPC.getPageSize()),
  44. {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
  45. }
  46. // Transfer allocation actions.
  47. std::swap(FR.Actions, G.allocActions());
  48. Parent.EPC.callSPSWrapperAsync<
  49. rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>(
  50. Parent.SAs.Finalize,
  51. [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
  52. Error SerializationErr, Error FinalizeErr) mutable {
  53. // FIXME: Release abandoned alloc.
  54. if (SerializationErr) {
  55. cantFail(std::move(FinalizeErr));
  56. OnFinalize(std::move(SerializationErr));
  57. } else if (FinalizeErr)
  58. OnFinalize(std::move(FinalizeErr));
  59. else
  60. OnFinalize(FinalizedAlloc(AllocAddr));
  61. },
  62. Parent.SAs.Allocator, std::move(FR));
  63. }
  64. void abandon(OnAbandonedFunction OnAbandoned) override {
  65. // FIXME: Return memory to pool instead.
  66. Parent.EPC.callSPSWrapperAsync<
  67. rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
  68. Parent.SAs.Deallocate,
  69. [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
  70. Error DeallocateErr) mutable {
  71. if (SerializationErr) {
  72. cantFail(std::move(DeallocateErr));
  73. OnAbandoned(std::move(SerializationErr));
  74. } else
  75. OnAbandoned(std::move(DeallocateErr));
  76. },
  77. Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
  78. }
  79. private:
  80. EPCGenericJITLinkMemoryManager &Parent;
  81. LinkGraph &G;
  82. ExecutorAddr AllocAddr;
  83. SegInfoMap Segs;
  84. };
  85. void EPCGenericJITLinkMemoryManager::allocate(const JITLinkDylib *JD,
  86. LinkGraph &G,
  87. OnAllocatedFunction OnAllocated) {
  88. BasicLayout BL(G);
  89. auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
  90. if (!Pages)
  91. return OnAllocated(Pages.takeError());
  92. EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorMemoryManagerReserveSignature>(
  93. SAs.Reserve,
  94. [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
  95. Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
  96. if (SerializationErr) {
  97. cantFail(AllocAddr.takeError());
  98. return OnAllocated(std::move(SerializationErr));
  99. }
  100. if (!AllocAddr)
  101. return OnAllocated(AllocAddr.takeError());
  102. completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
  103. },
  104. SAs.Allocator, Pages->total());
  105. }
  106. void EPCGenericJITLinkMemoryManager::deallocate(
  107. std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
  108. EPC.callSPSWrapperAsync<
  109. rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
  110. SAs.Deallocate,
  111. [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
  112. Error DeallocErr) mutable {
  113. if (SerErr) {
  114. cantFail(std::move(DeallocErr));
  115. OnDeallocated(std::move(SerErr));
  116. } else
  117. OnDeallocated(std::move(DeallocErr));
  118. },
  119. SAs.Allocator, Allocs);
  120. for (auto &A : Allocs)
  121. A.release();
  122. }
  123. void EPCGenericJITLinkMemoryManager::completeAllocation(
  124. ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
  125. InFlightAlloc::SegInfoMap SegInfos;
  126. ExecutorAddr NextSegAddr = AllocAddr;
  127. for (auto &KV : BL.segments()) {
  128. const auto &AG = KV.first;
  129. auto &Seg = KV.second;
  130. Seg.Addr = NextSegAddr;
  131. KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
  132. NextSegAddr += ExecutorAddrDiff(
  133. alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
  134. auto &SegInfo = SegInfos[AG];
  135. SegInfo.ContentSize = Seg.ContentSize;
  136. SegInfo.ZeroFillSize = Seg.ZeroFillSize;
  137. SegInfo.Addr = ExecutorAddr(Seg.Addr);
  138. SegInfo.WorkingMem = Seg.WorkingMem;
  139. }
  140. if (auto Err = BL.apply())
  141. return OnAllocated(std::move(Err));
  142. OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
  143. std::move(SegInfos)));
  144. }
  145. } // end namespace orc
  146. } // end namespace llvm