123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- //===---- EPCGenericJITLinkMemoryManager.cpp -- Mem management via EPC ----===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
- #include "llvm/ExecutionEngine/JITLink/JITLink.h"
- #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
- #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
- #include <limits>
- using namespace llvm::jitlink;
- namespace llvm {
- namespace orc {
- class EPCGenericJITLinkMemoryManager::InFlightAlloc
- : public jitlink::JITLinkMemoryManager::InFlightAlloc {
- public:
- // FIXME: The C++98 initializer is an attempt to work around compile failures
- // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
- // We should be able to switch this back to member initialization once that
- // issue is fixed.
- struct SegInfo {
- SegInfo() : WorkingMem(nullptr), ContentSize(0), ZeroFillSize(0) {}
- char *WorkingMem;
- ExecutorAddr Addr;
- uint64_t ContentSize;
- uint64_t ZeroFillSize;
- };
- using SegInfoMap = AllocGroupSmallMap<SegInfo>;
- InFlightAlloc(EPCGenericJITLinkMemoryManager &Parent, LinkGraph &G,
- ExecutorAddr AllocAddr, SegInfoMap Segs)
- : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
- void finalize(OnFinalizedFunction OnFinalize) override {
- tpctypes::FinalizeRequest FR;
- for (auto &KV : Segs) {
- assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
- FR.Segments.push_back(tpctypes::SegFinalizeRequest{
- KV.first,
- KV.second.Addr,
- alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
- Parent.EPC.getPageSize()),
- {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
- }
- // Transfer allocation actions.
- std::swap(FR.Actions, G.allocActions());
- Parent.EPC.callSPSWrapperAsync<
- rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>(
- Parent.SAs.Finalize,
- [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
- Error SerializationErr, Error FinalizeErr) mutable {
- // FIXME: Release abandoned alloc.
- if (SerializationErr) {
- cantFail(std::move(FinalizeErr));
- OnFinalize(std::move(SerializationErr));
- } else if (FinalizeErr)
- OnFinalize(std::move(FinalizeErr));
- else
- OnFinalize(FinalizedAlloc(AllocAddr));
- },
- Parent.SAs.Allocator, std::move(FR));
- }
- void abandon(OnAbandonedFunction OnAbandoned) override {
- // FIXME: Return memory to pool instead.
- Parent.EPC.callSPSWrapperAsync<
- rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
- Parent.SAs.Deallocate,
- [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
- Error DeallocateErr) mutable {
- if (SerializationErr) {
- cantFail(std::move(DeallocateErr));
- OnAbandoned(std::move(SerializationErr));
- } else
- OnAbandoned(std::move(DeallocateErr));
- },
- Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
- }
- private:
- EPCGenericJITLinkMemoryManager &Parent;
- LinkGraph &G;
- ExecutorAddr AllocAddr;
- SegInfoMap Segs;
- };
- void EPCGenericJITLinkMemoryManager::allocate(const JITLinkDylib *JD,
- LinkGraph &G,
- OnAllocatedFunction OnAllocated) {
- BasicLayout BL(G);
- auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
- if (!Pages)
- return OnAllocated(Pages.takeError());
- EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorMemoryManagerReserveSignature>(
- SAs.Reserve,
- [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
- Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
- if (SerializationErr) {
- cantFail(AllocAddr.takeError());
- return OnAllocated(std::move(SerializationErr));
- }
- if (!AllocAddr)
- return OnAllocated(AllocAddr.takeError());
- completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
- },
- SAs.Allocator, Pages->total());
- }
- void EPCGenericJITLinkMemoryManager::deallocate(
- std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
- EPC.callSPSWrapperAsync<
- rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
- SAs.Deallocate,
- [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
- Error DeallocErr) mutable {
- if (SerErr) {
- cantFail(std::move(DeallocErr));
- OnDeallocated(std::move(SerErr));
- } else
- OnDeallocated(std::move(DeallocErr));
- },
- SAs.Allocator, Allocs);
- for (auto &A : Allocs)
- A.release();
- }
- void EPCGenericJITLinkMemoryManager::completeAllocation(
- ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
- InFlightAlloc::SegInfoMap SegInfos;
- ExecutorAddr NextSegAddr = AllocAddr;
- for (auto &KV : BL.segments()) {
- const auto &AG = KV.first;
- auto &Seg = KV.second;
- Seg.Addr = NextSegAddr;
- KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
- NextSegAddr += ExecutorAddrDiff(
- alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
- auto &SegInfo = SegInfos[AG];
- SegInfo.ContentSize = Seg.ContentSize;
- SegInfo.ZeroFillSize = Seg.ZeroFillSize;
- SegInfo.Addr = ExecutorAddr(Seg.Addr);
- SegInfo.WorkingMem = Seg.WorkingMem;
- }
- if (auto Err = BL.apply())
- return OnAllocated(std::move(Err));
- OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
- std::move(SegInfos)));
- }
- } // end namespace orc
- } // end namespace llvm
|