Skip to content

Commit 8b60c05

Browse files
authored
Revert "[ORC] Make runAllocActions and runDeallocActions asynchorous." (#163480)
This reverts commit 3b5842c. The intent of the original commit was to begin enabling asynchronous alloation actions (calls attached to JIT'd memory initialization and deinitialization). The asynchronous allocation actions scheme was fleshed-out in a development branch, but ran into an issue: Functions implementing actions are allowed to live in JIT'd code (e.g. in the ORC runtime), but we can't genally rely on tail-call elimination kicking in. This resulting in dealloc actions returning via stack frames that had been deallocated, triggering segfaults. It's possible that there are other approaches that would allow asynchronous allocation actions to work, but they're not on the critical path for JIT improvements so for now we'll just revert.
1 parent 23848e6 commit 8b60c05

File tree

5 files changed

+47
-95
lines changed

5 files changed

+47
-95
lines changed

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_ALLOCATIONACTIONS_H
1414
#define LLVM_EXECUTIONENGINE_ORC_SHARED_ALLOCATIONACTIONS_H
1515

16-
#include "llvm/ADT/FunctionExtras.h"
1716
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
1817
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
1918
#include "llvm/Support/Compiler.h"
@@ -54,9 +53,6 @@ inline size_t numDeallocActions(const AllocActions &AAs) {
5453
AAs, [](const AllocActionCallPair &P) { return !!P.Dealloc; });
5554
}
5655

57-
using OnRunFinalizeActionsCompleteFn =
58-
unique_function<void(Expected<std::vector<WrapperFunctionCall>>)>;
59-
6056
/// Run finalize actions.
6157
///
6258
/// If any finalize action fails then the corresponding dealloc actions will be
@@ -67,16 +63,13 @@ using OnRunFinalizeActionsCompleteFn =
6763
/// be returned. The dealloc actions should be run by calling
6864
/// runDeallocationActions. If this function succeeds then the AA argument will
6965
/// be cleared before the function returns.
70-
LLVM_ABI void runFinalizeActions(AllocActions &AAs,
71-
OnRunFinalizeActionsCompleteFn OnComplete);
72-
73-
using OnRunDeallocActionsComeleteFn = unique_function<void(Error)>;
66+
LLVM_ABI Expected<std::vector<WrapperFunctionCall>>
67+
runFinalizeActions(AllocActions &AAs);
7468

7569
/// Run deallocation actions.
7670
/// Dealloc actions will be run in reverse order (from last element of DAs to
7771
/// first).
78-
LLVM_ABI void runDeallocActions(ArrayRef<WrapperFunctionCall> DAs,
79-
OnRunDeallocActionsComeleteFn OnComplete);
72+
LLVM_ABI Error runDeallocActions(ArrayRef<WrapperFunctionCall> DAs);
8073

8174
using SPSAllocActionCallPair =
8275
SPSTuple<SPSWrapperFunctionCall, SPSWrapperFunctionCall>;

llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -260,22 +260,17 @@ class InProcessMemoryManager::IPInFlightAlloc
260260
}
261261

262262
// Run finalization actions.
263-
using WrapperFunctionCall = orc::shared::WrapperFunctionCall;
264-
runFinalizeActions(
265-
G->allocActions(),
266-
[this, OnFinalized = std::move(OnFinalized)](
267-
Expected<std::vector<WrapperFunctionCall>> DeallocActions) mutable {
268-
completeFinalization(std::move(OnFinalized),
269-
std::move(DeallocActions));
270-
});
271-
}
263+
auto DeallocActions = runFinalizeActions(G->allocActions());
264+
if (!DeallocActions) {
265+
OnFinalized(DeallocActions.takeError());
266+
return;
267+
}
272268

273-
void abandon(OnAbandonedFunction OnAbandoned) override {
274-
Error Err = Error::success();
275-
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments))
276-
Err = joinErrors(std::move(Err), errorCodeToError(EC));
277-
if (auto EC = sys::Memory::releaseMappedMemory(StandardSegments))
278-
Err = joinErrors(std::move(Err), errorCodeToError(EC));
269+
// Release the finalize segments slab.
270+
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments)) {
271+
OnFinalized(errorCodeToError(EC));
272+
return;
273+
}
279274

280275
#ifndef NDEBUG
281276
// Set 'G' to null to flag that we've been successfully finalized.
@@ -284,22 +279,17 @@ class InProcessMemoryManager::IPInFlightAlloc
284279
G = nullptr;
285280
#endif
286281

287-
OnAbandoned(std::move(Err));
282+
// Continue with finalized allocation.
283+
OnFinalized(MemMgr.createFinalizedAlloc(std::move(StandardSegments),
284+
std::move(*DeallocActions)));
288285
}
289286

290-
private:
291-
void completeFinalization(
292-
OnFinalizedFunction OnFinalized,
293-
Expected<std::vector<orc::shared::WrapperFunctionCall>> DeallocActions) {
294-
295-
if (!DeallocActions)
296-
return OnFinalized(DeallocActions.takeError());
297-
298-
// Release the finalize segments slab.
299-
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments)) {
300-
OnFinalized(errorCodeToError(EC));
301-
return;
302-
}
287+
void abandon(OnAbandonedFunction OnAbandoned) override {
288+
Error Err = Error::success();
289+
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments))
290+
Err = joinErrors(std::move(Err), errorCodeToError(EC));
291+
if (auto EC = sys::Memory::releaseMappedMemory(StandardSegments))
292+
Err = joinErrors(std::move(Err), errorCodeToError(EC));
303293

304294
#ifndef NDEBUG
305295
// Set 'G' to null to flag that we've been successfully finalized.
@@ -308,11 +298,10 @@ class InProcessMemoryManager::IPInFlightAlloc
308298
G = nullptr;
309299
#endif
310300

311-
// Continue with finalized allocation.
312-
OnFinalized(MemMgr.createFinalizedAlloc(std::move(StandardSegments),
313-
std::move(*DeallocActions)));
301+
OnAbandoned(std::move(Err));
314302
}
315303

304+
private:
316305
Error applyProtections() {
317306
for (auto &KV : BL.segments()) {
318307
const auto &AG = KV.first;

llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -91,27 +91,17 @@ void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
9191
sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
9292
}
9393

94-
std::vector<shared::WrapperFunctionCall> DeinitializeActions;
95-
{
96-
std::promise<MSVCPExpected<std::vector<shared::WrapperFunctionCall>>> P;
97-
auto F = P.get_future();
98-
shared::runFinalizeActions(
99-
AI.Actions, [&](Expected<std::vector<shared::WrapperFunctionCall>> R) {
100-
P.set_value(std::move(R));
101-
});
102-
if (auto DeinitializeActionsOrErr = F.get())
103-
DeinitializeActions = std::move(*DeinitializeActionsOrErr);
104-
else
105-
return OnInitialized(DeinitializeActionsOrErr.takeError());
106-
}
94+
auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
95+
if (!DeinitializeActions)
96+
return OnInitialized(DeinitializeActions.takeError());
10797

10898
{
10999
std::lock_guard<std::mutex> Lock(Mutex);
110100

111101
// This is the maximum range whose permission have been possibly modified
112102
auto &Alloc = Allocations[MinAddr];
113103
Alloc.Size = MaxAddr - MinAddr;
114-
Alloc.DeinitializationActions = std::move(DeinitializeActions);
104+
Alloc.DeinitializationActions = std::move(*DeinitializeActions);
115105
Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
116106
}
117107

@@ -128,10 +118,10 @@ void InProcessMemoryMapper::deinitialize(
128118

129119
for (auto Base : llvm::reverse(Bases)) {
130120

131-
shared::runDeallocActions(
132-
Allocations[Base].DeinitializationActions, [&](Error Err) {
133-
AllErr = joinErrors(std::move(AllErr), std::move(Err));
134-
});
121+
if (Error Err = shared::runDeallocActions(
122+
Allocations[Base].DeinitializationActions)) {
123+
AllErr = joinErrors(std::move(AllErr), std::move(Err));
124+
}
135125

136126
// Reset protections to read/write so the area can be reused
137127
if (auto EC = sys::Memory::protectMappedMemory(

llvm/lib/ExecutionEngine/Orc/Shared/AllocationActions.cpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,31 @@ namespace llvm {
1212
namespace orc {
1313
namespace shared {
1414

15-
void runFinalizeActions(AllocActions &AAs,
16-
OnRunFinalizeActionsCompleteFn OnComplete) {
15+
Expected<std::vector<WrapperFunctionCall>>
16+
runFinalizeActions(AllocActions &AAs) {
1717
std::vector<WrapperFunctionCall> DeallocActions;
1818
DeallocActions.reserve(numDeallocActions(AAs));
1919

2020
for (auto &AA : AAs) {
2121
if (AA.Finalize)
22-
23-
if (auto Err = AA.Finalize.runWithSPSRetErrorMerged()) {
24-
while (!DeallocActions.empty()) {
25-
Err = joinErrors(std::move(Err),
26-
DeallocActions.back().runWithSPSRetErrorMerged());
27-
DeallocActions.pop_back();
28-
}
29-
return OnComplete(std::move(Err));
30-
}
22+
if (auto Err = AA.Finalize.runWithSPSRetErrorMerged())
23+
return joinErrors(std::move(Err), runDeallocActions(DeallocActions));
3124

3225
if (AA.Dealloc)
3326
DeallocActions.push_back(std::move(AA.Dealloc));
3427
}
3528

3629
AAs.clear();
37-
OnComplete(std::move(DeallocActions));
30+
return DeallocActions;
3831
}
3932

40-
void runDeallocActions(ArrayRef<WrapperFunctionCall> DAs,
41-
OnRunDeallocActionsComeleteFn OnComplete) {
33+
Error runDeallocActions(ArrayRef<WrapperFunctionCall> DAs) {
4234
Error Err = Error::success();
4335
while (!DAs.empty()) {
4436
Err = joinErrors(std::move(Err), DAs.back().runWithSPSRetErrorMerged());
4537
DAs = DAs.drop_back();
4638
}
47-
OnComplete(std::move(Err));
39+
return Err;
4840
}
4941

5042
} // namespace shared

llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@
99
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h"
1010
#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
1111
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12-
#include "llvm/Support/MSVCErrorWorkarounds.h"
1312
#include "llvm/Support/Process.h"
1413
#include "llvm/Support/WindowsError.h"
15-
#include <future>
1614
#include <sstream>
1715

1816
#if defined(LLVM_ON_UNIX)
@@ -183,24 +181,15 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
183181
}
184182

185183
// Run finalization actions and get deinitlization action list.
186-
std::vector<shared::WrapperFunctionCall> DeinitializeActions;
187-
{
188-
std::promise<MSVCPExpected<std::vector<shared::WrapperFunctionCall>>> P;
189-
auto F = P.get_future();
190-
shared::runFinalizeActions(
191-
FR.Actions, [&](Expected<std::vector<shared::WrapperFunctionCall>> R) {
192-
P.set_value(std::move(R));
193-
});
194-
if (auto DeinitializeActionsOrErr = F.get())
195-
DeinitializeActions = std::move(*DeinitializeActionsOrErr);
196-
else
197-
return DeinitializeActionsOrErr.takeError();
184+
auto DeinitializeActions = shared::runFinalizeActions(FR.Actions);
185+
if (!DeinitializeActions) {
186+
return DeinitializeActions.takeError();
198187
}
199188

200189
{
201190
std::lock_guard<std::mutex> Lock(Mutex);
202191
Allocations[MinAddr].DeinitializationActions =
203-
std::move(DeinitializeActions);
192+
std::move(*DeinitializeActions);
204193
Reservations[Reservation.toPtr<void *>()].Allocations.push_back(MinAddr);
205194
}
206195

@@ -221,11 +210,10 @@ Error ExecutorSharedMemoryMapperService::deinitialize(
221210
std::lock_guard<std::mutex> Lock(Mutex);
222211

223212
for (auto Base : llvm::reverse(Bases)) {
224-
shared::runDeallocActions(
225-
Allocations[Base].DeinitializationActions, [&](Error Err) {
226-
if (Err)
227-
AllErr = joinErrors(std::move(AllErr), std::move(Err));
228-
});
213+
if (Error Err = shared::runDeallocActions(
214+
Allocations[Base].DeinitializationActions)) {
215+
AllErr = joinErrors(std::move(AllErr), std::move(Err));
216+
}
229217

230218
// Remove the allocation from the allocation list of its reservation
231219
for (auto &Reservation : Reservations) {

0 commit comments

Comments
 (0)