Skip to content

Commit c2bc15f

Browse files
committed
Merge commit 'fbc2eaa4596e' from swift/release/5.9 into stable/20221013
Conflicts: lldb/source/Target/Target.cpp
2 parents ae7d786 + fbc2eaa commit c2bc15f

File tree

4 files changed

+115
-130
lines changed

4 files changed

+115
-130
lines changed

lldb/include/lldb/Core/SwiftScratchContextReader.h

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,64 +13,14 @@
1313
#ifndef liblldb_SwiftASTContextReader_h_
1414
#define liblldb_SwiftASTContextReader_h_
1515

16-
#include "llvm/Support/RWMutex.h"
16+
#include <shared_mutex>
1717

1818
namespace lldb_private {
1919

2020
class TypeSystemSwiftTypeRefForExpressions;
2121
class ExecutionContext;
2222
class ExecutionContextRef;
2323

24-
/// This is like llvm::sys::SmartRWMutex<true>, but with a try_lock method.
25-
///
26-
/// FIXME: Replace this with a C++14 shared_timed_mutex or a C++17
27-
/// share_mutex as soon as possible.
28-
class SharedMutex {
29-
llvm::sys::SmartRWMutex<true> m_impl;
30-
unsigned m_readers = 0;
31-
std::mutex m_reader_mutex;
32-
public:
33-
SharedMutex() = default;
34-
SharedMutex(const SharedMutex &) = delete;
35-
SharedMutex &operator=(const SharedMutex &) = delete;
36-
bool lock_shared() {
37-
std::lock_guard<std::mutex> lock(m_reader_mutex);
38-
++m_readers;
39-
return m_impl.lock_shared();
40-
}
41-
bool unlock_shared() {
42-
std::lock_guard<std::mutex> lock(m_reader_mutex);
43-
assert(m_readers > 0);
44-
--m_readers;
45-
return m_impl.unlock_shared();
46-
}
47-
bool try_lock() {
48-
std::lock_guard<std::mutex> lock(m_reader_mutex);
49-
return m_readers ? false : m_impl.lock();
50-
}
51-
bool unlock() { return m_impl.unlock(); }
52-
};
53-
54-
/// RAII acquisition of a reader lock.
55-
struct ScopedSharedMutexReader {
56-
SharedMutex *m_mutex;
57-
explicit ScopedSharedMutexReader(SharedMutex *m) : m_mutex(m) {
58-
if (m_mutex)
59-
m_mutex->lock_shared();
60-
}
61-
62-
ScopedSharedMutexReader(const ScopedSharedMutexReader &copy)
63-
: m_mutex(copy.m_mutex) {
64-
if (m_mutex)
65-
m_mutex->lock_shared();
66-
}
67-
68-
~ScopedSharedMutexReader() {
69-
if (m_mutex)
70-
m_mutex->unlock_shared();
71-
}
72-
};
73-
7424
/// A scratch Swift context pointer and its reader lock.
7525
/// The Swift scratch context may need to be replaced when it gets corrupted,
7626
/// for example due to incompatible ClangImporter options. This locking
@@ -97,27 +47,25 @@ struct ScopedSharedMutexReader {
9747
/// or even separate scratch contexts for each lldb::Module. But it
9848
/// will only do this if no client holds on to a read lock on \b
9949
/// m_scratch_typesystem_lock.
100-
class SwiftScratchContextReader : ScopedSharedMutexReader {
101-
TypeSystemSwiftTypeRefForExpressions *m_ptr;
50+
class SwiftScratchContextReader {
51+
std::shared_lock<std::shared_mutex> m_lock;
52+
TypeSystemSwiftTypeRefForExpressions *m_ts;
10253

10354
public:
104-
SwiftScratchContextReader(SharedMutex &mutex,
105-
TypeSystemSwiftTypeRefForExpressions &ctx)
106-
: ScopedSharedMutexReader(&mutex), m_ptr(&ctx) {
107-
assert(m_ptr && "invalid context");
108-
}
109-
110-
TypeSystemSwiftTypeRefForExpressions *get() {
111-
assert(m_ptr && "invalid context");
112-
return m_ptr;
113-
}
114-
55+
SwiftScratchContextReader(std::shared_lock<std::shared_mutex> &&lock,
56+
TypeSystemSwiftTypeRefForExpressions &ts);
57+
SwiftScratchContextReader(const SwiftScratchContextReader &) = delete;
58+
SwiftScratchContextReader(SwiftScratchContextReader &&other) = default;
59+
SwiftScratchContextReader &
60+
operator=(SwiftScratchContextReader &&other) = default;
61+
TypeSystemSwiftTypeRefForExpressions *get() { return m_ts; }
11562
TypeSystemSwiftTypeRefForExpressions *operator->() { return get(); }
11663
TypeSystemSwiftTypeRefForExpressions &operator*() { return *get(); }
11764
};
11865

11966
/// An RAII object that just acquires the reader lock.
120-
struct SwiftScratchContextLock : ScopedSharedMutexReader {
67+
struct SwiftScratchContextLock {
68+
std::shared_lock<std::shared_mutex> lock;
12169
SwiftScratchContextLock(const ExecutionContextRef *exe_ctx_ref);
12270
SwiftScratchContextLock(const ExecutionContext *exe_ctx);
12371
};

lldb/include/lldb/Target/Target.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,7 +1268,7 @@ class Target : public std::enable_shared_from_this<Target>,
12681268

12691269
#ifdef LLDB_ENABLE_SWIFT
12701270
/// Get the lock guarding the scratch typesystem from being re-initialized.
1271-
SharedMutex &GetSwiftScratchContextLock() {
1271+
std::shared_mutex &GetSwiftScratchContextLock() {
12721272
return m_scratch_typesystem_lock;
12731273
}
12741274

@@ -1706,7 +1706,7 @@ class Target : public std::enable_shared_from_this<Target>,
17061706
m_scratch_typesystem_for_module;
17071707

17081708
/// Guards the scratch typesystem from being re-initialized.
1709-
SharedMutex m_scratch_typesystem_lock;
1709+
std::shared_mutex m_scratch_typesystem_lock;
17101710

17111711
static void ImageSearchPathsChanged(const PathMappingList &path_list,
17121712
void *baton);

lldb/source/Core/ValueObjectDynamicValue.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,8 @@ bool ValueObjectDynamicValue::DynamicValueTypeInfoNeedsUpdate() {
450450

451451
#ifdef LLDB_ENABLE_SWIFT
452452
auto cached_ctx = m_value.GetCompilerType().GetTypeSystem();
453-
llvm::Optional<SwiftScratchContextReader> scratch_ctx =
454-
GetSwiftScratchContext();
453+
llvm::Optional<SwiftScratchContextReader> scratch_ctx(
454+
GetSwiftScratchContext());
455455

456456
if (!scratch_ctx || !cached_ctx)
457457
return true;

lldb/source/Target/Target.cpp

Lines changed: 98 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,12 +2427,12 @@ Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language,
24272427
if (swift_ast_ctx && (swift_ast_ctx->CheckProcessChanged() ||
24282428
swift_ast_ctx->HasFatalErrors())) {
24292429
// If it is safe to replace the scratch context, do so. If
2430-
// try_lock() fails, then higher stack frame (or another
2430+
// try_lock() fails, then a higher stack frame (or another
24312431
// thread) is holding a read lock to the scratch context and
24322432
// replacing it could cause a use-after-free later on.
2433-
if (GetSwiftScratchContextLock().try_lock()) {
2434-
auto unlock = llvm::make_scope_exit(
2435-
[this] { GetSwiftScratchContextLock().unlock(); });
2433+
auto &lock = GetSwiftScratchContextLock();
2434+
if (lock.try_lock()) {
2435+
std::lock_guard<std::shared_mutex> unlock(lock, std::adopt_lock);
24362436
if (m_use_scratch_typesystem_per_module)
24372437
DisplayFallbackSwiftContextErrors(swift_ast_ctx);
24382438
else if (StreamSP errs = GetDebugger().GetAsyncErrorStream()) {
@@ -2717,66 +2717,77 @@ llvm::Optional<SwiftScratchContextReader> Target::GetSwiftScratchContext(
27172717
}
27182718
}
27192719
}
2720-
2721-
auto get_or_create_fallback_context =
2722-
[&]() -> TypeSystemSwiftTypeRefForExpressions * {
2723-
if (!lldb_module || !m_use_scratch_typesystem_per_module)
2724-
return nullptr;
27252720

2726-
ModuleLanguage idx = {lldb_module, lldb::eLanguageTypeSwift};
2727-
auto cached = m_scratch_typesystem_for_module.find(idx);
2728-
if (cached != m_scratch_typesystem_for_module.end()) {
2729-
auto *cached_ts =
2730-
llvm::cast<TypeSystemSwiftTypeRefForExpressions>(cached->second.get());
2731-
if (!cached_ts)
2732-
return nullptr;
2721+
auto get_cached_module_ts =
2722+
[&](Module *lldb_module) -> TypeSystemSwiftTypeRefForExpressions * {
2723+
ModuleLanguage key = {lldb_module, lldb::eLanguageTypeSwift};
2724+
auto cached = m_scratch_typesystem_for_module.find(key);
2725+
if (cached != m_scratch_typesystem_for_module.end())
2726+
return llvm::cast<TypeSystemSwiftTypeRefForExpressions>(cached->second.get());
2727+
return nullptr;
2728+
};
2729+
2730+
auto maybe_create_fallback_context = [&]() {
2731+
ModuleLanguage key = {lldb_module, lldb::eLanguageTypeSwift};
2732+
if (auto *cached_ts = get_cached_module_ts(lldb_module)) {
27332733
auto *cached_ast_ctx =
27342734
llvm::dyn_cast_or_null<SwiftASTContextForExpressions>(
27352735
cached_ts->GetSwiftASTContext());
27362736
if (cached_ast_ctx && cached_ast_ctx->HasFatalErrors() &&
27372737
!m_cant_make_scratch_type_system.count(lldb::eLanguageTypeSwift)) {
27382738
DisplayFallbackSwiftContextErrors(cached_ast_ctx);
27392739
// Try again.
2740-
m_scratch_typesystem_for_module.erase(cached);
2741-
return nullptr;
2740+
// FIXME: Shouldn't this continue rather than return?
2741+
auto &lock = GetSwiftScratchContextLock();
2742+
if (!lock.try_lock()) {
2743+
if (log)
2744+
log->Printf("module scratch context has errors but couldn't "
2745+
"acquire scratch context lock\n");
2746+
return;
2747+
}
2748+
std::lock_guard<std::shared_mutex> unlock(lock, std::adopt_lock);
2749+
m_scratch_typesystem_for_module.erase(key);
2750+
if (log)
2751+
log->Printf("erased module-wide scratch context with errors\n");
2752+
return;
27422753
}
27432754
if (log)
27442755
log->PutCString("returned cached module-wide scratch context");
2745-
return cached_ts;
2756+
return;
27462757
}
27472758

27482759
if (!create_on_demand) {
27492760
if (log)
27502761
log->PutCString("not allowed to create a new context");
2751-
return nullptr;
2762+
return;
27522763
}
27532764

2754-
// Call for its side effects of establishing the Swift scratch type system.
2765+
// Call for its side effects of establishing the Swift scratch type
2766+
// system.
27552767
auto type_system_or_err =
27562768
GetScratchTypeSystemForLanguage(eLanguageTypeSwift, false);
27572769
if (!type_system_or_err) {
27582770
llvm::consumeError(type_system_or_err.takeError());
2759-
return nullptr;
2771+
return;
27602772
}
27612773

2762-
if (!GetSwiftScratchContextLock().try_lock()) {
2774+
auto &lock = GetSwiftScratchContextLock();
2775+
if (!lock.try_lock()) {
27632776
if (log)
27642777
log->PutCString("couldn't acquire scratch context lock");
2765-
return nullptr;
2778+
return;
27662779
}
2780+
std::lock_guard<std::shared_mutex> unlock(lock, std::adopt_lock);
27672781

2768-
auto unlock = llvm::make_scope_exit(
2769-
[this] { GetSwiftScratchContextLock().unlock(); });
2770-
2771-
// With the lock held, get the current scratch type system. This ensures the
2772-
// current instance is used even in the unlikely event it was changed during
2773-
// the brief window between the call to `GetScratchTypeSystemForLanguage`
2774-
// and taking the lock.
2782+
// With the lock held, get the current scratch type system. This ensures
2783+
// the current instance is used even in the unlikely event it was changed
2784+
// during the brief window between the call to
2785+
// `GetScratchTypeSystemForLanguage` and taking the lock.
27752786
type_system_or_err = m_scratch_type_system_map.GetTypeSystemForLanguage(
27762787
eLanguageTypeSwift, this, false);
27772788
if (!type_system_or_err) {
27782789
llvm::consumeError(type_system_or_err.takeError());
2779-
return nullptr;
2790+
return;
27802791
}
27812792

27822793
if (auto *global_scratch_ctx =
@@ -2790,42 +2801,55 @@ llvm::Optional<SwiftScratchContextReader> Target::GetSwiftScratchContext(
27902801
auto typesystem_sp = std::make_shared<TypeSystemSwiftTypeRefForExpressions>(
27912802
lldb::eLanguageTypeSwift, *this, *lldb_module);
27922803
typesystem_sp->GetSwiftASTContext();
2793-
m_scratch_typesystem_for_module.insert({idx, typesystem_sp});
2804+
m_scratch_typesystem_for_module.insert({key, typesystem_sp});
27942805
if (log)
27952806
log->PutCString("created module-wide scratch context");
2796-
return typesystem_sp.get();
2807+
return;
27972808
};
27982809

2799-
auto *swift_scratch_ctx = get_or_create_fallback_context();
2800-
if (!swift_scratch_ctx) {
2801-
if (log)
2802-
log->PutCString("returned project-wide scratch context");
2810+
llvm::Optional<SwiftScratchContextReader> reader;
2811+
if (lldb_module && m_use_scratch_typesystem_per_module) {
2812+
maybe_create_fallback_context();
2813+
std::shared_lock<std::shared_mutex> lock(GetSwiftScratchContextLock());
2814+
if (auto *cached_ts = get_cached_module_ts(lldb_module)) {
2815+
reader = SwiftScratchContextReader(std::move(lock), *cached_ts);
2816+
if (log)
2817+
log->PutCString("returned project-wide scratch context");
2818+
}
2819+
}
2820+
// FIXME: Don't return the project-wide context after requesting the
2821+
// module-wide one.
2822+
if (!reader) {
2823+
std::shared_lock<std::shared_mutex> lock(GetSwiftScratchContextLock());
28032824
auto type_system_or_err =
28042825
GetScratchTypeSystemForLanguage(eLanguageTypeSwift, create_on_demand);
2805-
if (type_system_or_err)
2806-
swift_scratch_ctx =
2807-
llvm::cast_or_null<TypeSystemSwiftTypeRefForExpressions>(
2808-
type_system_or_err->get());
2809-
else
2826+
if (type_system_or_err) {
2827+
if (auto *ts = llvm::cast_or_null<TypeSystemSwiftTypeRefForExpressions>(
2828+
type_system_or_err->get())) {
2829+
reader = SwiftScratchContextReader(std::move(lock), *ts);
2830+
if (log)
2831+
log->Printf("returned project-wide scratch context\n");
2832+
}
2833+
} else
28102834
llvm::consumeError(type_system_or_err.takeError());
28112835
}
28122836

2813-
StackFrameSP frame_sp = exe_scope.CalculateStackFrame();
2814-
if (frame_sp && frame_sp.get() && swift_scratch_ctx) {
2815-
SymbolContext sc =
2816-
frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
2817-
Status status = swift_scratch_ctx->PerformCompileUnitImports(sc);
2818-
if (status.Fail())
2819-
Debugger::ReportError(status.AsCString(), GetDebugger().GetID());
2837+
if (reader) {
2838+
// Perform compile unit imports.
2839+
assert(reader->get());
2840+
StackFrameSP frame_sp = exe_scope.CalculateStackFrame();
2841+
if (frame_sp && frame_sp.get()) {
2842+
SymbolContext sc =
2843+
frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
2844+
Status status = reader->get()->PerformCompileUnitImports(sc);
2845+
if (status.Fail())
2846+
Debugger::ReportError(status.AsCString(), GetDebugger().GetID());
2847+
}
28202848
}
2821-
2822-
if (!swift_scratch_ctx)
2823-
return llvm::None;
2824-
return SwiftScratchContextReader(GetSwiftScratchContextLock(),
2825-
*swift_scratch_ctx);
2849+
return reader;
28262850
}
28272851

2828-
static SharedMutex *
2852+
static std::shared_mutex *
28292853
GetSwiftScratchContextMutex(const ExecutionContext *exe_ctx) {
28302854
if (!exe_ctx)
28312855
return nullptr;
@@ -2835,11 +2859,20 @@ GetSwiftScratchContextMutex(const ExecutionContext *exe_ctx) {
28352859
return nullptr;
28362860
}
28372861

2862+
SwiftScratchContextReader::SwiftScratchContextReader(
2863+
std::shared_lock<std::shared_mutex> &&lock,
2864+
TypeSystemSwiftTypeRefForExpressions &ts)
2865+
: m_lock(std::move(lock)), m_ts(&ts) {}
2866+
28382867
SwiftScratchContextLock::SwiftScratchContextLock(
2839-
const ExecutionContext *exe_ctx)
2840-
: ScopedSharedMutexReader(GetSwiftScratchContextMutex(exe_ctx)) {}
2868+
const ExecutionContext *exe_ctx) {
2869+
if (auto *mutex = GetSwiftScratchContextMutex(exe_ctx)) {
2870+
std::shared_lock<std::shared_mutex> tmp(*mutex);
2871+
lock.swap(tmp);
2872+
}
2873+
}
28412874

2842-
static SharedMutex *
2875+
static std::shared_mutex *
28432876
GetSwiftScratchContextMutex(const ExecutionContextRef *exe_ctx_ref) {
28442877
if (!exe_ctx_ref)
28452878
return nullptr;
@@ -2848,8 +2881,12 @@ GetSwiftScratchContextMutex(const ExecutionContextRef *exe_ctx_ref) {
28482881
}
28492882

28502883
SwiftScratchContextLock::SwiftScratchContextLock(
2851-
const ExecutionContextRef *exe_ctx_ref)
2852-
: ScopedSharedMutexReader(GetSwiftScratchContextMutex(exe_ctx_ref)) {}
2884+
const ExecutionContextRef *exe_ctx_ref) {
2885+
if (auto *mutex = GetSwiftScratchContextMutex(exe_ctx_ref)) {
2886+
std::shared_lock<std::shared_mutex> tmp(*mutex);
2887+
lock.swap(tmp);
2888+
}
2889+
}
28532890

28542891
void Target::DisplayFallbackSwiftContextErrors(
28552892
SwiftASTContextForExpressions *swift_ast_ctx) {

0 commit comments

Comments
 (0)