Skip to content

Commit 5ad09de

Browse files
committed
Revert "Re-revert r343129."
This reverts commit 4e2557d. llvm-svn: 343161
1 parent 27ec210 commit 5ad09de

File tree

3 files changed

+114
-8
lines changed

3 files changed

+114
-8
lines changed

llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "llvm/IR/LLVMContext.h"
1818
#include "llvm/IR/Module.h"
19+
#include "llvm/Support/Compiler.h"
1920

2021
#include <functional>
2122
#include <memory>
@@ -40,7 +41,7 @@ class ThreadSafeContext {
4041
public:
4142

4243
// RAII based lock for ThreadSafeContext.
43-
class Lock {
44+
class LLVM_NODISCARD Lock {
4445
private:
4546
using UnderlyingLock = std::lock_guard<std::recursive_mutex>;
4647
public:
@@ -85,16 +86,26 @@ class ThreadSafeModule {
8586
/// null context.
8687
ThreadSafeModule() = default;
8788

89+
ThreadSafeModule(ThreadSafeModule &&Other) = default;
90+
91+
ThreadSafeModule& operator=(ThreadSafeModule &&Other) {
92+
// We have to explicitly define this move operator to copy the fields in
93+
// reverse order (i.e. module first) to ensure the dependencies are
94+
// protected: The old module that is being overwritten must be destroyed
95+
// *before* the context that it depends on.
96+
M = std::move(Other.M);
97+
TSCtx = std::move(Other.TSCtx);
98+
return *this;
99+
}
100+
88101
/// Construct a ThreadSafeModule from a unique_ptr<Module> and a
89102
/// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the
90103
/// given context.
91-
ThreadSafeModule(std::unique_ptr<Module> M,
92-
std::unique_ptr<LLVMContext> Ctx)
93-
: M(std::move(M)), TSCtx(std::move(Ctx)) {}
104+
ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx)
105+
: TSCtx(std::move(Ctx)), M(std::move(M)) {}
94106

95-
ThreadSafeModule(std::unique_ptr<Module> M,
96-
ThreadSafeContext TSCtx)
97-
: M(std::move(M)), TSCtx(std::move(TSCtx)) {}
107+
ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx)
108+
: TSCtx(std::move(TSCtx)), M(std::move(M)) {}
98109

99110
Module* getModule() { return M.get(); }
100111

@@ -109,8 +120,8 @@ class ThreadSafeModule {
109120
}
110121

111122
private:
112-
std::unique_ptr<Module> M;
113123
ThreadSafeContext TSCtx;
124+
std::unique_ptr<Module> M;
114125
};
115126

116127
using GVPredicate = std::function<bool(const GlobalValue&)>;

llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_llvm_unittest(OrcJITTests
2626
RTDyldObjectLinkingLayerTest.cpp
2727
RTDyldObjectLinkingLayer2Test.cpp
2828
SymbolStringPoolTest.cpp
29+
ThreadSafeModuleTest.cpp
2930
)
3031

3132
target_link_libraries(OrcJITTests PRIVATE ${ORC_JIT_TEST_LIBS})
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//===--- ThreadSafeModuleTest.cpp - Test basic use of ThreadSafeModule ----===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
11+
#include "gtest/gtest.h"
12+
13+
#include <atomic>
14+
#include <future>
15+
#include <thread>
16+
17+
using namespace llvm;
18+
using namespace llvm::orc;
19+
20+
namespace {
21+
22+
TEST(ThreadSafeModuleTest, ContextWhollyOwnedByOneModule) {
23+
// Test that ownership of a context can be transferred to a single
24+
// ThreadSafeModule.
25+
ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
26+
ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()),
27+
std::move(TSCtx));
28+
}
29+
30+
TEST(ThreadSafeModuleTest, ContextOwnershipSharedByTwoModules) {
31+
// Test that ownership of a context can be shared between more than one
32+
// ThreadSafeModule.
33+
ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
34+
35+
ThreadSafeModule TSM1(llvm::make_unique<Module>("M1", *TSCtx.getContext()),
36+
TSCtx);
37+
ThreadSafeModule TSM2(llvm::make_unique<Module>("M2", *TSCtx.getContext()),
38+
std::move(TSCtx));
39+
}
40+
41+
TEST(ThreadSafeModuleTest, ContextOwnershipSharedWithClient) {
42+
// Test that ownership of a context can be shared with a client-held
43+
// ThreadSafeContext so that it can be re-used for new modules.
44+
ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
45+
46+
{
47+
// Create and destroy a module.
48+
ThreadSafeModule TSM1(llvm::make_unique<Module>("M1", *TSCtx.getContext()),
49+
TSCtx);
50+
}
51+
52+
// Verify that the context is still available for re-use.
53+
ThreadSafeModule TSM2(llvm::make_unique<Module>("M2", *TSCtx.getContext()),
54+
std::move(TSCtx));
55+
}
56+
57+
TEST(ThreadSafeModuleTest, ThreadSafeModuleMoveAssignment) {
58+
// Move assignment needs to move the module before the context (opposite
59+
// to the field order) to ensure that overwriting with an empty
60+
// ThreadSafeModule does not destroy the context early.
61+
ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
62+
ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()),
63+
std::move(TSCtx));
64+
TSM = ThreadSafeModule();
65+
}
66+
67+
TEST(ThreadSafeModuleTest, BasicContextLockAPI) {
68+
// Test that basic lock API calls work.
69+
ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
70+
ThreadSafeModule TSM(llvm::make_unique<Module>("M", *TSCtx.getContext()),
71+
TSCtx);
72+
73+
{ auto L = TSCtx.getLock(); }
74+
75+
{ auto L = TSM.getContextLock(); }
76+
}
77+
78+
TEST(ThreadSafeModuleTest, ContextLockPreservesContext) {
79+
// Test that the existence of a context lock preserves the attached
80+
// context.
81+
// The trick to verify this is a bit of a hack: We attach a Module
82+
// (without the ThreadSafeModule wrapper) to the context, then verify
83+
// that this Module destructs safely (which it will not if its context
84+
// has been destroyed) even though all references to the context have
85+
// been thrown away (apart from the lock).
86+
87+
ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>());
88+
auto L = TSCtx.getLock();
89+
auto &Ctx = *TSCtx.getContext();
90+
auto M = llvm::make_unique<Module>("M", Ctx);
91+
TSCtx = ThreadSafeContext();
92+
}
93+
94+
} // end anonymous namespace

0 commit comments

Comments
 (0)