Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ORC] Add a new MemoryMapper-based JITLinkMemoryManager implementation.
MapperJITLinkMemoryManager supports executor memory management using any implementation of MemoryMapper to do the transfer such as InProcessMapper or SharedMemoryMapper. Reviewed By: lhames Differential Revision: https://reviews.llvm.org/D129495
- Loading branch information
Showing
9 changed files
with
291 additions
and
9 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
llvm/include/llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
//===--------------- MapperJITLinkMemoryManager.h -*- C++ -*---------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Implements JITLinkMemoryManager using MemoryMapper | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_EXECUTIONENGINE_ORC_MAPPERJITLINKMEMORYMANAGER_H | ||
#define LLVM_EXECUTIONENGINE_ORC_MAPPERJITLINKMEMORYMANAGER_H | ||
|
||
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" | ||
#include "llvm/ExecutionEngine/Orc/Core.h" | ||
#include "llvm/ExecutionEngine/Orc/MemoryMapper.h" | ||
|
||
namespace llvm { | ||
namespace orc { | ||
|
||
class MapperJITLinkMemoryManager : public jitlink::JITLinkMemoryManager { | ||
public: | ||
MapperJITLinkMemoryManager(std::unique_ptr<MemoryMapper> Mapper); | ||
|
||
template <class MemoryMapperType, class... Args> | ||
static Expected<std::unique_ptr<MapperJITLinkMemoryManager>> | ||
CreateWithMapper(Args &&...A) { | ||
auto Mapper = MemoryMapperType::Create(std::forward<Args>(A)...); | ||
if (!Mapper) | ||
return Mapper.takeError(); | ||
|
||
return std::make_unique<MapperJITLinkMemoryManager>(std::move(*Mapper)); | ||
} | ||
|
||
void allocate(const jitlink::JITLinkDylib *JD, jitlink::LinkGraph &G, | ||
OnAllocatedFunction OnAllocated) override; | ||
// synchronous overload | ||
using JITLinkMemoryManager::allocate; | ||
|
||
void deallocate(std::vector<FinalizedAlloc> Allocs, | ||
OnDeallocatedFunction OnDeallocated) override; | ||
// synchronous overload | ||
using JITLinkMemoryManager::deallocate; | ||
|
||
private: | ||
class InFlightAlloc; | ||
|
||
std::unique_ptr<MemoryMapper> Mapper; | ||
}; | ||
|
||
} // end namespace orc | ||
} // end namespace llvm | ||
|
||
#endif // LLVM_EXECUTIONENGINE_ORC_MAPPERJITLINKMEMORYMANAGER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
//=== MapperJITLinkMemoryManager.cpp - Memory management with MemoryMapper ===// | ||
// | ||
// 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/MapperJITLinkMemoryManager.h" | ||
|
||
#include "llvm/ExecutionEngine/JITLink/JITLink.h" | ||
#include "llvm/Support/Process.h" | ||
|
||
#include <limits> | ||
|
||
using namespace llvm::jitlink; | ||
|
||
namespace llvm { | ||
namespace orc { | ||
|
||
class MapperJITLinkMemoryManager::InFlightAlloc | ||
: public JITLinkMemoryManager::InFlightAlloc { | ||
public: | ||
InFlightAlloc(MapperJITLinkMemoryManager &Parent, LinkGraph &G, | ||
ExecutorAddr AllocAddr, | ||
std::vector<MemoryMapper::AllocInfo::SegInfo> Segs) | ||
: Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {} | ||
|
||
void finalize(OnFinalizedFunction OnFinalize) override { | ||
MemoryMapper::AllocInfo AI; | ||
AI.MappingBase = AllocAddr; | ||
|
||
std::swap(AI.Segments, Segs); | ||
std::swap(AI.Actions, G.allocActions()); | ||
|
||
Parent.Mapper->initialize(AI, [&](Expected<ExecutorAddr> Result) { | ||
if (!Result) { | ||
OnFinalize(Result.takeError()); | ||
return; | ||
} | ||
|
||
OnFinalize(FinalizedAlloc(*Result)); | ||
}); | ||
} | ||
|
||
void abandon(OnAbandonedFunction OnFinalize) override { | ||
Parent.Mapper->release({AllocAddr}, std::move(OnFinalize)); | ||
} | ||
|
||
private: | ||
MapperJITLinkMemoryManager &Parent; | ||
LinkGraph &G; | ||
ExecutorAddr AllocAddr; | ||
std::vector<MemoryMapper::AllocInfo::SegInfo> Segs; | ||
}; | ||
|
||
MapperJITLinkMemoryManager::MapperJITLinkMemoryManager( | ||
std::unique_ptr<MemoryMapper> Mapper) | ||
: Mapper(std::move(Mapper)) {} | ||
|
||
void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G, | ||
OnAllocatedFunction OnAllocated) { | ||
BasicLayout BL(G); | ||
|
||
// find required address space | ||
auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(Mapper->getPageSize()); | ||
if (!SegsSizes) { | ||
OnAllocated(SegsSizes.takeError()); | ||
return; | ||
} | ||
|
||
// Check if total size fits in address space | ||
if (SegsSizes->total() > std::numeric_limits<size_t>::max()) { | ||
OnAllocated(make_error<JITLinkError>( | ||
formatv("Total requested size {:x} for graph {} exceeds address space", | ||
SegsSizes->total(), G.getName()))); | ||
return; | ||
} | ||
|
||
Mapper->reserve( | ||
SegsSizes->total(), | ||
[this, &G, BL = std::move(BL), OnAllocated = std::move(OnAllocated)]( | ||
Expected<ExecutorAddrRange> Result) mutable { | ||
if (!Result) { | ||
return OnAllocated(Result.takeError()); | ||
} | ||
|
||
auto NextSegAddr = Result->Start; | ||
|
||
std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos; | ||
|
||
for (auto &KV : BL.segments()) { | ||
auto &AG = KV.first; | ||
auto &Seg = KV.second; | ||
|
||
auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize; | ||
|
||
Seg.Addr = NextSegAddr; | ||
Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize); | ||
|
||
NextSegAddr += alignTo(TotalSize, Mapper->getPageSize()); | ||
|
||
MemoryMapper::AllocInfo::SegInfo SI; | ||
SI.Offset = Seg.Addr - Result->Start; | ||
SI.ContentSize = Seg.ContentSize; | ||
SI.ZeroFillSize = Seg.ZeroFillSize; | ||
SI.Prot = (toSysMemoryProtectionFlags(AG.getMemProt())); | ||
SI.WorkingMem = Seg.WorkingMem; | ||
|
||
SegInfos.push_back(SI); | ||
} | ||
|
||
if (auto Err = BL.apply()) { | ||
OnAllocated(std::move(Err)); | ||
return; | ||
} | ||
|
||
OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start, | ||
std::move(SegInfos))); | ||
}); | ||
} | ||
|
||
void MapperJITLinkMemoryManager::deallocate( | ||
std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) { | ||
std::vector<ExecutorAddr> Bases; | ||
Bases.reserve(Allocs.size()); | ||
for (auto &FA : Allocs) { | ||
Bases.push_back(FA.getAddress()); | ||
FA.release(); | ||
} | ||
Mapper->release(Bases, std::move(OnDeallocated)); | ||
} | ||
|
||
} // end namespace orc | ||
} // end namespace llvm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
//===-------------- MapperJITLinkMemoryManagerTest.cpp ----------------===// | ||
// | ||
// 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 "OrcTestCommon.h" | ||
|
||
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h" | ||
|
||
#include "llvm/Testing/Support/Error.h" | ||
|
||
#include <vector> | ||
|
||
using namespace llvm; | ||
using namespace llvm::jitlink; | ||
using namespace llvm::orc; | ||
using namespace llvm::orc::shared; | ||
|
||
namespace { | ||
|
||
TEST(MapperJITLinkMemoryManagerTest, InProcess) { | ||
auto MemMgr = cantFail( | ||
MapperJITLinkMemoryManager::CreateWithMapper<InProcessMemoryMapper>()); | ||
|
||
StringRef Hello = "hello"; | ||
auto SSA = jitlink::SimpleSegmentAlloc::Create( | ||
*MemMgr, nullptr, {{jitlink::MemProt::Read, {Hello.size(), Align(1)}}}); | ||
EXPECT_THAT_EXPECTED(SSA, Succeeded()); | ||
auto SegInfo = SSA->getSegInfo(jitlink::MemProt::Read); | ||
memcpy(SegInfo.WorkingMem.data(), Hello.data(), Hello.size()); | ||
|
||
auto FA = SSA->finalize(); | ||
EXPECT_THAT_EXPECTED(FA, Succeeded()); | ||
|
||
ExecutorAddr TargetAddr(SegInfo.Addr); | ||
|
||
const char *TargetMem = TargetAddr.toPtr<const char *>(); | ||
StringRef TargetHello(TargetMem, Hello.size()); | ||
EXPECT_EQ(Hello, TargetHello); | ||
|
||
auto Err2 = MemMgr->deallocate(std::move(*FA)); | ||
EXPECT_THAT_ERROR(std::move(Err2), Succeeded()); | ||
} | ||
|
||
} // namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters