EPCGenericJITLinkMemoryManager.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. KV.first,
  40. KV.second.Addr,
  41. alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
  42. Parent.EPC.getPageSize()),
  43. {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
  44. }
  45. // Transfer allocation actions.
  46. std::swap(FR.Actions, G.allocActions());
  47. Parent.EPC.callSPSWrapperAsync<
  48. rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>(
  49. Parent.SAs.Finalize,
  50. [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
  51. Error SerializationErr, Error FinalizeErr) mutable {
  52. // FIXME: Release abandoned alloc.
  53. if (SerializationErr) {
  54. cantFail(std::move(FinalizeErr));
  55. OnFinalize(std::move(SerializationErr));
  56. } else if (FinalizeErr)
  57. OnFinalize(std::move(FinalizeErr));
  58. else
  59. OnFinalize(FinalizedAlloc(AllocAddr));
  60. },
  61. Parent.SAs.Allocator, std::move(FR));
  62. }
  63. void abandon(OnAbandonedFunction OnAbandoned) override {
  64. // FIXME: Return memory to pool instead.
  65. Parent.EPC.callSPSWrapperAsync<
  66. rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
  67. Parent.SAs.Deallocate,
  68. [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
  69. Error DeallocateErr) mutable {
  70. if (SerializationErr) {
  71. cantFail(std::move(DeallocateErr));
  72. OnAbandoned(std::move(SerializationErr));
  73. } else
  74. OnAbandoned(std::move(DeallocateErr));
  75. },
  76. Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
  77. }
  78. private:
  79. EPCGenericJITLinkMemoryManager &Parent;
  80. LinkGraph &G;
  81. ExecutorAddr AllocAddr;
  82. SegInfoMap Segs;
  83. };
  84. void EPCGenericJITLinkMemoryManager::allocate(const JITLinkDylib *JD,
  85. LinkGraph &G,
  86. OnAllocatedFunction OnAllocated) {
  87. BasicLayout BL(G);
  88. auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
  89. if (!Pages)
  90. return OnAllocated(Pages.takeError());
  91. EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorMemoryManagerReserveSignature>(
  92. SAs.Reserve,
  93. [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
  94. Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
  95. if (SerializationErr) {
  96. cantFail(AllocAddr.takeError());
  97. return OnAllocated(std::move(SerializationErr));
  98. }
  99. if (!AllocAddr)
  100. return OnAllocated(AllocAddr.takeError());
  101. completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
  102. },
  103. SAs.Allocator, Pages->total());
  104. }
  105. void EPCGenericJITLinkMemoryManager::deallocate(
  106. std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
  107. EPC.callSPSWrapperAsync<
  108. rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
  109. SAs.Deallocate,
  110. [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
  111. Error DeallocErr) mutable {
  112. if (SerErr) {
  113. cantFail(std::move(DeallocErr));
  114. OnDeallocated(std::move(SerErr));
  115. } else
  116. OnDeallocated(std::move(DeallocErr));
  117. },
  118. SAs.Allocator, Allocs);
  119. for (auto &A : Allocs)
  120. A.release();
  121. }
  122. void EPCGenericJITLinkMemoryManager::completeAllocation(
  123. ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
  124. InFlightAlloc::SegInfoMap SegInfos;
  125. ExecutorAddr NextSegAddr = AllocAddr;
  126. for (auto &KV : BL.segments()) {
  127. const auto &AG = KV.first;
  128. auto &Seg = KV.second;
  129. Seg.Addr = NextSegAddr;
  130. KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
  131. NextSegAddr += ExecutorAddrDiff(
  132. alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
  133. auto &SegInfo = SegInfos[AG];
  134. SegInfo.ContentSize = Seg.ContentSize;
  135. SegInfo.ZeroFillSize = Seg.ZeroFillSize;
  136. SegInfo.Addr = ExecutorAddr(Seg.Addr);
  137. SegInfo.WorkingMem = Seg.WorkingMem;
  138. }
  139. if (auto Err = BL.apply())
  140. return OnAllocated(std::move(Err));
  141. OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
  142. std::move(SegInfos)));
  143. }
  144. } // end namespace orc
  145. } // end namespace llvm