Skip to content

Commit 78b083d

Browse files
committed
[ORC] Add finalization & deallocation actions, SimpleExecutorMemoryManager class
Finalization and deallocation actions are a key part of the upcoming JITLinkMemoryManager redesign: They generalize the existing finalization and deallocate concepts (basically "copy-and-mprotect", and "munmap") to include support for arbitrary registration and deregistration of parts of JIT linked code. This allows us to register and deregister eh-frames, TLV sections, language metadata, etc. using regular memory management calls with no additional IPC/RPC overhead, which should both improve JIT performance and simplify interactions between ORC and the ORC runtime. The SimpleExecutorMemoryManager class provides executor-side support for memory management operations, including finalization and deallocation actions. This support is being added in advance of the rest of the memory manager redesign as it will simplify the introduction of an EPC based RuntimeDyld::MemoryManager (since eh-frame registration/deregistration will be expressible as actions). The new RuntimeDyld::MemoryManager will in turn allow us to remove older remote allocators that are blocking the rest of the memory manager changes.
1 parent fe950cb commit 78b083d

17 files changed

+730
-149
lines changed

llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,17 @@ namespace orc {
2727
class EPCGenericJITLinkMemoryManager : public jitlink::JITLinkMemoryManager {
2828
public:
2929
/// Function addresses for memory access.
30-
struct FuncAddrs {
30+
struct SymbolAddrs {
31+
ExecutorAddress Allocator;
3132
ExecutorAddress Reserve;
3233
ExecutorAddress Finalize;
3334
ExecutorAddress Deallocate;
3435
};
3536

3637
/// Create an EPCGenericJITLinkMemoryManager instance from a given set of
3738
/// function addrs.
38-
EPCGenericJITLinkMemoryManager(ExecutorProcessControl &EPC, FuncAddrs FAs)
39-
: EPC(EPC), FAs(FAs) {}
39+
EPCGenericJITLinkMemoryManager(ExecutorProcessControl &EPC, SymbolAddrs SAs)
40+
: EPC(EPC), SAs(SAs) {}
4041

4142
Expected<std::unique_ptr<Allocation>>
4243
allocate(const jitlink::JITLinkDylib *JD,
@@ -46,7 +47,7 @@ class EPCGenericJITLinkMemoryManager : public jitlink::JITLinkMemoryManager {
4647
class Alloc;
4748

4849
ExecutorProcessControl &EPC;
49-
FuncAddrs FAs;
50+
SymbolAddrs SAs;
5051
};
5152

5253
} // end namespace orc

llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,27 @@ namespace llvm {
2121
namespace orc {
2222
namespace rt {
2323

24-
extern const char *MemoryReserveWrapperName;
25-
extern const char *MemoryFinalizeWrapperName;
26-
extern const char *MemoryDeallocateWrapperName;
24+
extern const char *SimpleExecutorMemoryManagerInstanceName;
25+
extern const char *SimpleExecutorMemoryManagerReserveWrapperName;
26+
extern const char *SimpleExecutorMemoryManagerFinalizeWrapperName;
27+
extern const char *SimpleExecutorMemoryManagerDeallocateWrapperName;
28+
2729
extern const char *MemoryWriteUInt8sWrapperName;
2830
extern const char *MemoryWriteUInt16sWrapperName;
2931
extern const char *MemoryWriteUInt32sWrapperName;
3032
extern const char *MemoryWriteUInt64sWrapperName;
3133
extern const char *MemoryWriteBuffersWrapperName;
3234
extern const char *RunAsMainWrapperName;
3335

34-
using SPSMemoryReserveSignature =
35-
shared::SPSExpected<shared::SPSExecutorAddress>(uint64_t);
36-
using SPSMemoryFinalizeSignature = shared::SPSError(shared::SPSFinalizeRequest);
37-
using SPSMemoryDeallocateSignature =
38-
shared::SPSError(shared::SPSExecutorAddress, uint64_t);
36+
using SPSSimpleExecutorMemoryManagerReserveSignature =
37+
shared::SPSExpected<shared::SPSExecutorAddress>(shared::SPSExecutorAddress,
38+
uint64_t);
39+
using SPSSimpleExecutorMemoryManagerFinalizeSignature =
40+
shared::SPSError(shared::SPSExecutorAddress, shared::SPSFinalizeRequest);
41+
using SPSSimpleExecutorMemoryManagerDeallocateSignature =
42+
shared::SPSError(shared::SPSExecutorAddress,
43+
shared::SPSSequence<shared::SPSExecutorAddress>);
44+
3945
using SPSRunAsMainSignature = int64_t(shared::SPSExecutorAddress,
4046
shared::SPSSequence<shared::SPSString>);
4147

llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ExecutionEngine/JITSymbol.h"
2020
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
2121
#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
22+
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
2223
#include "llvm/Support/Memory.h"
2324

2425
#include <vector>
@@ -68,14 +69,42 @@ inline std::string getWireProtectionFlagsStr(WireProtectionFlags WPF) {
6869
return Result;
6970
}
7071

72+
struct SupportFunctionCall {
73+
using FnTy = shared::detail::CWrapperFunctionResult(const char *ArgData,
74+
size_t ArgSize);
75+
ExecutorAddress Func;
76+
ExecutorAddress ArgData;
77+
uint64_t ArgSize;
78+
79+
Error run() {
80+
shared::WrapperFunctionResult WFR(
81+
Func.toPtr<FnTy *>()(ArgData.toPtr<const char *>(), ArgSize));
82+
if (const char *ErrMsg = WFR.getOutOfBandError())
83+
return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
84+
if (!WFR.empty())
85+
return make_error<StringError>("Unexpected result bytes from "
86+
"support function call",
87+
inconvertibleErrorCode());
88+
return Error::success();
89+
}
90+
};
91+
92+
struct AllocationActionsPair {
93+
SupportFunctionCall Finalize;
94+
SupportFunctionCall Deallocate;
95+
};
96+
7197
struct SegFinalizeRequest {
7298
WireProtectionFlags Prot;
7399
ExecutorAddress Addr;
74100
uint64_t Size;
75101
ArrayRef<char> Content;
76102
};
77103

78-
using FinalizeRequest = std::vector<SegFinalizeRequest>;
104+
struct FinalizeRequest {
105+
std::vector<SegFinalizeRequest> Segments;
106+
std::vector<AllocationActionsPair> Actions;
107+
};
79108

80109
template <typename T> struct UIntWrite {
81110
UIntWrite() = default;
@@ -120,11 +149,18 @@ namespace shared {
120149

121150
class SPSMemoryProtectionFlags {};
122151

152+
using SPSSupportFunctionCall =
153+
SPSTuple<SPSExecutorAddress, SPSExecutorAddress, uint64_t>;
154+
123155
using SPSSegFinalizeRequest =
124156
SPSTuple<SPSMemoryProtectionFlags, SPSExecutorAddress, uint64_t,
125157
SPSSequence<char>>;
126158

127-
using SPSFinalizeRequest = SPSSequence<SPSSegFinalizeRequest>;
159+
using SPSAllocationActionsPair =
160+
SPSTuple<SPSSupportFunctionCall, SPSSupportFunctionCall>;
161+
162+
using SPSFinalizeRequest = SPSTuple<SPSSequence<SPSSegFinalizeRequest>,
163+
SPSSequence<SPSAllocationActionsPair>>;
128164

129165
template <typename T>
130166
using SPSMemoryAccessUIntWrite = SPSTuple<SPSExecutorAddress, T>;
@@ -160,6 +196,48 @@ class SPSSerializationTraits<SPSMemoryProtectionFlags,
160196
}
161197
};
162198

199+
template <>
200+
class SPSSerializationTraits<SPSSupportFunctionCall,
201+
tpctypes::SupportFunctionCall> {
202+
using AL = SPSSupportFunctionCall::AsArgList;
203+
204+
public:
205+
static size_t size(const tpctypes::SupportFunctionCall &SFC) {
206+
return AL::size(SFC.Func, SFC.ArgData, SFC.ArgSize);
207+
}
208+
209+
static bool serialize(SPSOutputBuffer &OB,
210+
const tpctypes::SupportFunctionCall &SFC) {
211+
return AL::serialize(OB, SFC.Func, SFC.ArgData, SFC.ArgSize);
212+
}
213+
214+
static bool deserialize(SPSInputBuffer &IB,
215+
tpctypes::SupportFunctionCall &SFC) {
216+
return AL::deserialize(IB, SFC.Func, SFC.ArgData, SFC.ArgSize);
217+
}
218+
};
219+
220+
template <>
221+
class SPSSerializationTraits<SPSAllocationActionsPair,
222+
tpctypes::AllocationActionsPair> {
223+
using AL = SPSAllocationActionsPair::AsArgList;
224+
225+
public:
226+
static size_t size(const tpctypes::AllocationActionsPair &AAP) {
227+
return AL::size(AAP.Finalize, AAP.Deallocate);
228+
}
229+
230+
static bool serialize(SPSOutputBuffer &OB,
231+
const tpctypes::AllocationActionsPair &AAP) {
232+
return AL::serialize(OB, AAP.Finalize, AAP.Deallocate);
233+
}
234+
235+
static bool deserialize(SPSInputBuffer &IB,
236+
tpctypes::AllocationActionsPair &AAP) {
237+
return AL::deserialize(IB, AAP.Finalize, AAP.Deallocate);
238+
}
239+
};
240+
163241
template <>
164242
class SPSSerializationTraits<SPSSegFinalizeRequest,
165243
tpctypes::SegFinalizeRequest> {
@@ -181,6 +259,25 @@ class SPSSerializationTraits<SPSSegFinalizeRequest,
181259
}
182260
};
183261

262+
template <>
263+
class SPSSerializationTraits<SPSFinalizeRequest, tpctypes::FinalizeRequest> {
264+
using FRAL = SPSFinalizeRequest::AsArgList;
265+
266+
public:
267+
static size_t size(const tpctypes::FinalizeRequest &FR) {
268+
return FRAL::size(FR.Segments, FR.Actions);
269+
}
270+
271+
static bool serialize(SPSOutputBuffer &OB,
272+
const tpctypes::FinalizeRequest &FR) {
273+
return FRAL::serialize(OB, FR.Segments, FR.Actions);
274+
}
275+
276+
static bool deserialize(SPSInputBuffer &IB, tpctypes::FinalizeRequest &FR) {
277+
return FRAL::deserialize(IB, FR.Segments, FR.Actions);
278+
}
279+
};
280+
184281
template <typename T>
185282
class SPSSerializationTraits<SPSMemoryAccessUIntWrite<T>,
186283
tpctypes::UIntWrite<T>> {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===- ExecutorService.h - Provide bootstrap symbols to session -*- C++ -*-===//
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+
//
9+
// Provides a service by supplying some set of bootstrap symbols.
10+
//
11+
// FIXME: The functionality in this file should be moved to the ORC runtime.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORBOOTSTRAPSERVICE_H
16+
#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORBOOTSTRAPSERVICE_H
17+
18+
#include "llvm/ADT/StringMap.h"
19+
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
20+
21+
namespace llvm {
22+
namespace orc {
23+
24+
class ExecutorBootstrapService {
25+
public:
26+
virtual ~ExecutorBootstrapService();
27+
28+
virtual void
29+
addBootstrapSymbols(StringMap<ExecutorAddress> &BootstrapSymbols) = 0;
30+
virtual Error shutdown() = 0;
31+
};
32+
33+
} // end namespace orc
34+
} // end namespace llvm
35+
36+
#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORBOOTSTRAPSERVICE_H
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===---------------- SimpleExecutorMemoryManager.h -------------*- C++ -*-===//
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+
//
9+
// A simple allocator class suitable for basic remote-JIT use.
10+
//
11+
// FIXME: The functionality in this file should be moved to the ORC runtime.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEEXECUTORMEMORYMANAGER_H
16+
#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEEXECUTORMEMORYMANAGER_H
17+
18+
#include "llvm/ADT/DenseMap.h"
19+
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
20+
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
21+
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
22+
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
23+
#include "llvm/Support/Error.h"
24+
25+
#include <mutex>
26+
27+
namespace llvm {
28+
namespace orc {
29+
namespace rt_bootstrap {
30+
31+
/// Simple page-based allocator.
32+
class SimpleExecutorMemoryManager : public ExecutorBootstrapService {
33+
public:
34+
virtual ~SimpleExecutorMemoryManager();
35+
36+
Expected<ExecutorAddress> allocate(uint64_t Size);
37+
Error finalize(tpctypes::FinalizeRequest &FR);
38+
Error deallocate(const std::vector<ExecutorAddress> &Bases);
39+
40+
Error shutdown() override;
41+
void addBootstrapSymbols(StringMap<ExecutorAddress> &M) override;
42+
43+
private:
44+
struct Allocation {
45+
size_t Size = 0;
46+
std::vector<tpctypes::SupportFunctionCall> DeallocationActions;
47+
};
48+
49+
using AllocationsMap = DenseMap<void *, Allocation>;
50+
51+
Error deallocateImpl(void *Base, Allocation &A);
52+
53+
static llvm::orc::shared::detail::CWrapperFunctionResult
54+
reserveWrapper(const char *ArgData, size_t ArgSize);
55+
56+
static llvm::orc::shared::detail::CWrapperFunctionResult
57+
finalizeWrapper(const char *ArgData, size_t ArgSize);
58+
59+
static llvm::orc::shared::detail::CWrapperFunctionResult
60+
deallocateWrapper(const char *ArgData, size_t ArgSize);
61+
62+
std::mutex M;
63+
AllocationsMap Allocations;
64+
};
65+
66+
} // end namespace rt_bootstrap
67+
} // end namespace orc
68+
} // end namespace llvm
69+
70+
#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEEXECUTORMEMORYMANAGER_H

0 commit comments

Comments
 (0)