Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//===- SimpleRemoteMemoryMapper.h - Remote memory mapper --------*- 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
//
//===----------------------------------------------------------------------===//
//
// A simple memory mapper that uses EPC calls to implement reserve, initialize,
// deinitialize, and release.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEMEMORYMAPPER_H
#define LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEMEMORYMAPPER_H

#include "llvm/ExecutionEngine/Orc/MemoryMapper.h"

namespace llvm::orc {

/// Manages remote memory by making SPS-based EPC calls.
class LLVM_ABI SimpleRemoteMemoryMapper final : public MemoryMapper {
public:
struct SymbolAddrs {
ExecutorAddr Instance;
ExecutorAddr Reserve;
ExecutorAddr Initialize;
ExecutorAddr Deinitialize;
ExecutorAddr Release;
};

SimpleRemoteMemoryMapper(ExecutorProcessControl &EPC, SymbolAddrs SAs);

static Expected<std::unique_ptr<SimpleRemoteMemoryMapper>>
Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
return std::make_unique<SimpleRemoteMemoryMapper>(EPC, SAs);
}

unsigned int getPageSize() override { return EPC.getPageSize(); }

/// Reserves memory in the remote process by calling a remote
/// SPS-wrapper-function with signature
///
/// SPSExpected<SPSExecutorAddr>(uint64_t Size).
///
/// On success, returns the base address of the reserved range.
void reserve(size_t NumBytes, OnReservedFunction OnReserved) override;

char *prepare(jitlink::LinkGraph &G, ExecutorAddr Addr,
size_t ContentSize) override;

/// Initializes memory within a previously reserved region (applying
/// protections and running any finalization actions) by calling a remote
/// SPS-wrapper-function with signature
///
/// SPSExpected<SPSExecutorAddr>(SPSFinalizeRequest)
///
/// On success, returns a key that can be used to deinitialize the region.
void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override;

/// Given a series of keys from previous initialize calls, deinitialize
/// previously initialized memory regions (running dealloc actions, resetting
/// permissions and decommitting if possible) by calling a remote
/// SPS-wrapper-function with signature
///
/// SPSError(SPSSequence<SPSExecutorAddr> Keys)
///
void deinitialize(ArrayRef<ExecutorAddr> Allocations,
OnDeinitializedFunction OnDeInitialized) override;

/// Given a sequence of base addresses from previous reserve calls, release
/// the underlying ranges (deinitializing any remaining regions within them)
/// by calling a remote SPS-wrapper-function with signature
///
/// SPSError(SPSSequence<SPSExecutorAddr> Bases)
///
void release(ArrayRef<ExecutorAddr> Reservations,
OnReleasedFunction OnRelease) override;

private:
ExecutorProcessControl &EPC;
SymbolAddrs SAs;
};

} // namespace llvm::orc

#endif // LLVM_EXECUTIONENGINE_ORC_SIMPLEREMOTEMEMORYMAPPER_H
1 change: 1 addition & 0 deletions llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ add_llvm_component_library(LLVMOrcJIT
SectCreate.cpp
SelfExecutorProcessControl.cpp
SimpleRemoteEPC.cpp
SimpleRemoteMemoryMapper.cpp
Speculation.cpp
SpeculateAnalyses.cpp
ExecutorProcessControl.cpp
Expand Down
104 changes: 104 additions & 0 deletions llvm/lib/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//===---- SimpleRemoteMemoryMapper.cpp - Remote memory mapper ----*- 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
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h"

#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"

namespace llvm::orc {

SimpleRemoteMemoryMapper::SimpleRemoteMemoryMapper(ExecutorProcessControl &EPC,
SymbolAddrs SAs)
: EPC(EPC), SAs(SAs) {}

void SimpleRemoteMemoryMapper::reserve(size_t NumBytes,
OnReservedFunction OnReserved) {
EPC.callSPSWrapperAsync<rt::SPSSimpleRemoteMemoryMapReserveSignature>(
SAs.Reserve,
[NumBytes, OnReserved = std::move(OnReserved)](
Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
if (SerializationErr) {
cantFail(Result.takeError());
return OnReserved(std::move(SerializationErr));
}

if (Result)
OnReserved(ExecutorAddrRange(*Result, NumBytes));
else
OnReserved(Result.takeError());
},
SAs.Instance, static_cast<uint64_t>(NumBytes));
}

char *SimpleRemoteMemoryMapper::prepare(jitlink::LinkGraph &G,
ExecutorAddr Addr, size_t ContentSize) {
return G.allocateBuffer(ContentSize).data();
}

void SimpleRemoteMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
OnInitializedFunction OnInitialized) {

tpctypes::FinalizeRequest FR;

std::swap(FR.Actions, AI.Actions);
FR.Segments.reserve(AI.Segments.size());

for (auto Seg : AI.Segments)
FR.Segments.push_back({Seg.AG, AI.MappingBase + Seg.Offset,
Seg.ContentSize + Seg.ZeroFillSize,
ArrayRef<char>(Seg.WorkingMem, Seg.ContentSize)});

EPC.callSPSWrapperAsync<rt::SPSSimpleRemoteMemoryMapInitializeSignature>(
SAs.Initialize,
[OnInitialized = std::move(OnInitialized)](
Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
if (SerializationErr) {
cantFail(Result.takeError());
return OnInitialized(std::move(SerializationErr));
}

OnInitialized(std::move(Result));
},
SAs.Instance, std::move(FR));
}

void SimpleRemoteMemoryMapper::deinitialize(
ArrayRef<ExecutorAddr> Allocations,
MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
EPC.callSPSWrapperAsync<rt::SPSSimpleRemoteMemoryMapDeinitializeSignature>(
SAs.Deinitialize,
[OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
Error Result) mutable {
if (SerializationErr) {
cantFail(std::move(Result));
return OnDeinitialized(std::move(SerializationErr));
}

OnDeinitialized(std::move(Result));
},
SAs.Instance, Allocations);
}

void SimpleRemoteMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
OnReleasedFunction OnReleased) {
EPC.callSPSWrapperAsync<rt::SPSSimpleRemoteMemoryMapReleaseSignature>(
SAs.Release,
[OnReleased = std::move(OnReleased)](Error SerializationErr,
Error Result) mutable {
if (SerializationErr) {
cantFail(std::move(Result));
return OnReleased(std::move(SerializationErr));
}

return OnReleased(std::move(Result));
},
SAs.Instance, Bases);
}

} // namespace llvm::orc
58 changes: 50 additions & 8 deletions llvm/tools/llvm-jitlink/llvm-jitlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "llvm/ExecutionEngine/Orc/SectCreate.h"
#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
Expand Down Expand Up @@ -312,10 +313,19 @@ static cl::opt<bool>
cl::desc("Show FailedToMaterialize errors"),
cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<bool> UseSharedMemory(
"use-shared-memory",
cl::desc("Use shared memory to transfer generated code and data"),
cl::init(false), cl::cat(JITLinkCategory));
enum class MemMgr { Default, Generic, SimpleRemote, Shared };

static cl::opt<MemMgr> UseMemMgr(
"use-memmgr", cl::desc("Choose memory manager"), cl::init(MemMgr::Generic),
cl::values(clEnumValN(MemMgr::Default, "default",
"Use setup default (InProcess or EPCGeneric)"),
clEnumValN(MemMgr::Generic, "generic",
"Generic remote memory manager"),
clEnumValN(MemMgr::SimpleRemote, "simple-remote",
"Mapper memory manager with simple-remote backend"),
clEnumValN(MemMgr::Shared, "shared",
"Mapper memory manager with shared-memory manager")),
cl::cat(JITLinkCategory));

static cl::opt<std::string>
OverrideTriple("triple", cl::desc("Override target triple detection"),
Expand Down Expand Up @@ -717,6 +727,27 @@ static std::unique_ptr<JITLinkMemoryManager> createInProcessMemoryManager() {
SlabSize));
}

Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
createSimpleRemoteMemoryManager(SimpleRemoteEPC &SREPC) {
SimpleRemoteMemoryMapper::SymbolAddrs SAs;
if (auto Err = SREPC.getBootstrapSymbols(
{{SAs.Instance, rt::SimpleExecutorMemoryManagerInstanceName},
{SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
{SAs.Initialize,
rt::SimpleExecutorMemoryManagerInitializeWrapperName},
{SAs.Deinitialize,
rt::SimpleExecutorMemoryManagerDeinitializeWrapperName},
{SAs.Release, rt::SimpleExecutorMemoryManagerReleaseWrapperName}}))
return std::move(Err);
#ifdef _WIN32
size_t SlabSize = 1024 * 1024;
#else
size_t SlabSize = 1024 * 1024 * 1024;
#endif
return MapperJITLinkMemoryManager::CreateWithMapper<SimpleRemoteMemoryMapper>(
SlabSize, SREPC, SAs);
}

Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
createSharedMemoryManager(SimpleRemoteEPC &SREPC) {
SharedMemoryMapper::SymbolAddrs SAs;
Expand Down Expand Up @@ -745,6 +776,19 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC) {
SlabSize, SREPC, SAs);
}

static void setupEPCRemoteMemoryManager(SimpleRemoteEPC::Setup &S) {
switch (UseMemMgr) {
case MemMgr::Default:
case MemMgr::Generic:
break;
case MemMgr::SimpleRemote:
S.CreateMemoryManager = createSimpleRemoteMemoryManager;
break;
case MemMgr::Shared:
S.CreateMemoryManager = createSharedMemoryManager;
break;
}
}

static Expected<MaterializationUnit::Interface>
getTestObjectFileInterface(Session &S, MemoryBufferRef O) {
Expand Down Expand Up @@ -904,8 +948,7 @@ static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() {
close(FromExecutor[WriteEnd]);

auto S = SimpleRemoteEPC::Setup();
if (UseSharedMemory)
S.CreateMemoryManager = createSharedMemoryManager;
setupEPCRemoteMemoryManager(S);

return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
std::make_unique<DynamicThreadPoolTaskDispatcher>(MaterializationThreads),
Expand Down Expand Up @@ -994,8 +1037,7 @@ static Expected<std::unique_ptr<ExecutorProcessControl>> connectToExecutor() {
return SockFD.takeError();

auto S = SimpleRemoteEPC::Setup();
if (UseSharedMemory)
S.CreateMemoryManager = createSharedMemoryManager;
setupEPCRemoteMemoryManager(S);

return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
Expand Down