Skip to content

Commit a765952

Browse files
Merge pull request #8719 from augusto2112/guard-ast
Introduce LockGuarded and make swift::ASTContext accesses thread safe
2 parents 9e23627 + 356d8a4 commit a765952

File tree

12 files changed

+399
-336
lines changed

12 files changed

+399
-336
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp

Lines changed: 183 additions & 209 deletions
Large diffs are not rendered by default.

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
#ifndef liblldb_SwiftExpressionParser_h_
1414
#define liblldb_SwiftExpressionParser_h_
1515

16+
#include "Plugins/TypeSystem/Swift/SwiftASTContext.h"
1617
#include "SwiftASTManipulator.h"
1718

1819
#include "Plugins/ExpressionParser/Clang/IRForTarget.h"
20+
#include "SwiftPersistentExpressionState.h"
1921
#include "lldb/Utility/ArchSpec.h"
2022
#include "lldb/Utility/Status.h"
2123
#include "lldb/Expression/ExpressionParser.h"
@@ -24,13 +26,15 @@
2426
#include "lldb/Target/Target.h"
2527
#include "lldb/lldb-public.h"
2628

29+
#include "swift/SIL/SILDebuggerClient.h"
2730
#include <string>
2831
#include <vector>
2932

3033
namespace lldb_private {
3134

3235
class IRExecutionUnit;
3336
class SwiftLanguageRuntime;
37+
class LLDBNameLookup;
3438
//----------------------------------------------------------------------
3539
/// @class SwiftExpressionParser SwiftExpressionParser.h
3640
/// "lldb/Expression/SwiftExpressionParser.h"
@@ -178,6 +182,27 @@ class SwiftExpressionParser : public ExpressionParser {
178182
typedef std::map<const char *, SILVariableInfo> SILVariableMap;
179183

180184
private:
185+
/// This holds the result of ParseAndImport.
186+
struct ParsedExpression {
187+
std::unique_ptr<SwiftASTManipulator> code_manipulator;
188+
swift::ModuleDecl &module;
189+
LLDBNameLookup &external_lookup;
190+
swift::SourceFile &source_file;
191+
std::string main_filename;
192+
unsigned buffer_id;
193+
};
194+
195+
/// Attempt to parse an expression and import all the Swift modules
196+
/// the expression and its context depend on.
197+
llvm::Expected<ParsedExpression>
198+
ParseAndImport(SwiftASTContext::ScopedDiagnostics &expr_diagnostics,
199+
SwiftExpressionParser::SILVariableMap &variable_map,
200+
unsigned &buffer_id, DiagnosticManager &diagnostic_manager);
201+
202+
/// Initialize the SwiftASTContext and return the wrapped
203+
/// ThreadSafeASTContext when successful.
204+
ThreadSafeASTContext GetASTContext(DiagnosticManager &diagnostic_manager);
205+
181206
/// The expression to be parsed.
182207
Expression &m_expr;
183208
/// The context to use for IR generation.
@@ -206,7 +231,41 @@ class SwiftExpressionParser : public ExpressionParser {
206231

207232
/// Indicates whether the call to Parse of this type is cacheable.
208233
bool m_is_cacheable;
234+
235+
/// Once token to initialize the swift::ASTContext.
236+
llvm::once_flag m_ast_init_once_flag;
237+
238+
/// Indicates if the ThreadSafeASTContext was initialized correctly.
239+
bool m_ast_init_successful;
240+
};
241+
242+
class LLDBNameLookup : public swift::SILDebuggerClient {
243+
public:
244+
LLDBNameLookup(swift::SourceFile &source_file,
245+
SwiftExpressionParser::SILVariableMap &variable_map,
246+
SymbolContext &sc, ExecutionContextScope &exe_scope);
247+
248+
swift::SILValue emitLValueForVariable(swift::VarDecl *var,
249+
swift::SILBuilder &builder) override;
250+
251+
SwiftPersistentExpressionState::SwiftDeclMap &GetStagedDecls();
252+
253+
void RegisterTypeAliases(
254+
llvm::SmallVectorImpl<swift::TypeAliasDecl *> &type_aliases);
255+
256+
protected:
257+
Log *m_log;
258+
swift::SourceFile &m_source_file;
259+
SwiftExpressionParser::SILVariableMap &m_variable_map;
260+
SymbolContext m_sc;
261+
SwiftPersistentExpressionState *m_persistent_vars = nullptr;
262+
263+
// Subclasses stage globalized decls in this map. They get copied
264+
// over to the SwiftPersistentVariable store if the parse succeeds.
265+
SwiftPersistentExpressionState::SwiftDeclMap m_staged_decls;
266+
llvm::SmallVector<swift::TypeAliasDecl *> m_type_aliases;
209267
};
268+
210269
} // namespace lldb_private
211270

212271
#endif // liblldb_SwiftExpressionParser_h_

lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ void SwiftREPL::CompleteCode(const std::string &current_code,
574574
SwiftASTContextForExpressions *swift_ast = m_swift_ast;
575575

576576
if (swift_ast) {
577-
swift::ASTContext *ast = swift_ast->GetASTContext();
577+
ThreadSafeASTContext ast = swift_ast->GetASTContext();
578578
swift::REPLCompletions completions;
579579
SourceModule completion_module_info;
580580
completion_module_info.path.push_back(ConstString("repl"));
@@ -587,7 +587,7 @@ void SwiftREPL::CompleteCode(const std::string &current_code,
587587
repl_module = swift_ast->CreateModule(completion_module_info, error,
588588
importInfo);
589589
std::optional<unsigned> bufferID;
590-
swift::SourceFile *repl_source_file = new (*ast) swift::SourceFile(
590+
swift::SourceFile *repl_source_file = new (**ast) swift::SourceFile(
591591
*repl_module, swift::SourceFileKind::Main, bufferID);
592592
repl_module->addFile(*repl_source_file);
593593
swift::performImportResolution(*repl_source_file);

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ static llvm::Error AddVariableInfo(
378378
ss.flush();
379379
log->Printf("Adding injected self: type (%p) context(%p) is: %s",
380380
static_cast<void *>(swift_type.getPointer()),
381-
static_cast<void *>(ast_context.GetASTContext()), s.c_str());
381+
static_cast<void *>(*ast_context.GetASTContext()), s.c_str());
382382
}
383383
// A one-off clone of variable_sp with the type replaced by target_type.
384384
auto patched_variable_sp = std::make_shared<lldb_private::Variable>(

lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ static std::string TranslateObjCNameToSwiftName(std::string className,
150150
}
151151
};
152152

153-
MyConsumer consumer(swift::ObjCSelector(*ctx->GetASTContext(), numArguments,
153+
ThreadSafeASTContext ast_ctx = ctx->GetASTContext();
154+
MyConsumer consumer(swift::ObjCSelector(**ast_ctx, numArguments,
154155
selectorIdentifiers));
155156
// FIXME(mracek): Switch to a new API that translates the Clang class name
156157
// to Swift class name, once this API exists. Now we assume they are the same.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===----------------- LockGuarded.h ----------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef liblldb_SwiftLockGuarded_h_
14+
#define liblldb_SwiftLockGuarded_h_
15+
16+
#include <mutex>
17+
18+
namespace lldb_private {
19+
/// A generic wrapper around a resource which holds a lock to ensure
20+
/// exclusive access.
21+
template <typename Resource> struct LockGuarded {
22+
LockGuarded(Resource *resource, std::recursive_mutex &mutex)
23+
: m_resource(resource), m_lock(mutex, std::adopt_lock) {}
24+
25+
LockGuarded() = default;
26+
27+
Resource *operator->() const { return m_resource; }
28+
29+
Resource *operator*() const { return m_resource; }
30+
31+
operator bool() const { return m_resource != nullptr; }
32+
33+
private:
34+
Resource *m_resource;
35+
std::unique_lock<std::recursive_mutex> m_lock;
36+
};
37+
38+
} // namespace lldb_private
39+
#endif

lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContextInterface.h

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/ADT/SmallVector.h"
2525
#include "llvm/ADT/StringRef.h"
2626
#include "llvm/Support/Memory.h"
27+
#include "LockGuarded.h"
2728

2829
namespace swift {
2930
namespace Demangle {
@@ -146,31 +147,6 @@ class ReflectionContextInterface {
146147
StripSignedPointer(swift::remote::RemoteAbsolutePointer pointer) = 0;
147148
};
148149

149-
/// A wrapper around TargetReflectionContext, which holds a lock to ensure
150-
/// exclusive access.
151-
struct ThreadSafeReflectionContext {
152-
ThreadSafeReflectionContext(ReflectionContextInterface *reflection_ctx,
153-
std::recursive_mutex &mutex)
154-
: m_reflection_ctx(reflection_ctx), m_lock(mutex, std::adopt_lock) {}
155-
156-
static ThreadSafeReflectionContext MakeInvalid() {
157-
// This exists so we can create an "empty" reflection context in the stub
158-
// language runtime.
159-
static std::recursive_mutex mutex;
160-
return ThreadSafeReflectionContext(nullptr, mutex);
161-
}
162-
163-
ReflectionContextInterface *operator->() const { return m_reflection_ctx; }
164-
165-
operator bool() const { return m_reflection_ctx != nullptr; }
166-
167-
private:
168-
ReflectionContextInterface *m_reflection_ctx;
169-
// This lock operates on a recursive mutex because the initialization
170-
// of ReflectionContext recursive calls itself (see
171-
// SwiftLanguageRuntimeImpl::SetupReflection).
172-
std::lock_guard<std::recursive_mutex> m_lock;
173-
};
174-
150+
using ThreadSafeReflectionContext = LockGuarded<ReflectionContextInterface>;
175151
} // namespace lldb_private
176152
#endif

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ class SwiftLanguageRuntimeStub {
235235

236236
ThreadSafeReflectionContext GetReflectionContext() {
237237
STUB_LOG();
238-
return ThreadSafeReflectionContext::MakeInvalid();
238+
return ThreadSafeReflectionContext();
239239
}
240240

241241
bool GetDynamicTypeAndAddress(ValueObject &in_value,

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,15 @@ class TypeBase;
5151
} // namespace swift
5252

5353
namespace lldb_private {
54-
struct ThreadSafeReflectionContext;
54+
template <typename T>
55+
struct LockGuarded;
5556

5657
class SwiftLanguageRuntimeStub;
5758
class SwiftLanguageRuntimeImpl;
5859
class ReflectionContextInterface;
5960

61+
using ThreadSafeReflectionContext = LockGuarded<ReflectionContextInterface>;
62+
6063
class SwiftLanguageRuntime : public LanguageRuntime {
6164
protected:
6265
SwiftLanguageRuntime(Process *process);

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,18 @@ swift::remoteAST::RemoteASTContext &
5959
SwiftLanguageRuntimeImpl::GetRemoteASTContext(SwiftASTContext &swift_ast_ctx) {
6060
// If we already have a remote AST context for this AST context,
6161
// return it.
62-
auto known = m_remote_ast_contexts.find(swift_ast_ctx.GetASTContext());
62+
ThreadSafeASTContext ast_ctx = swift_ast_ctx.GetASTContext();
63+
auto known = m_remote_ast_contexts.find(*ast_ctx);
6364
if (known != m_remote_ast_contexts.end())
6465
return *known->second;
6566

6667
// Initialize a new remote AST context.
6768
(void)GetReflectionContext();
6869
auto remote_ast_up = std::make_unique<swift::remoteAST::RemoteASTContext>(
69-
*swift_ast_ctx.GetASTContext(), GetMemoryReader());
70+
**ast_ctx, GetMemoryReader());
7071
auto &remote_ast = *remote_ast_up;
7172
m_remote_ast_contexts.insert(
72-
{swift_ast_ctx.GetASTContext(), std::move(remote_ast_up)});
73+
{*ast_ctx, std::move(remote_ast_up)});
7374
return remote_ast;
7475
}
7576

@@ -521,7 +522,8 @@ SwiftLanguageRuntimeImpl::GetMetadataPromise(const SymbolContext *sc,
521522
if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
522523
return nullptr;
523524

524-
auto key = std::make_pair(swift_ast_ctx->GetASTContext(), addr);
525+
ThreadSafeASTContext ast_ctx = swift_ast_ctx->GetASTContext();
526+
auto key = std::make_pair(*ast_ctx, addr);
525527
auto iter = m_promises_map.find(key);
526528
if (iter != m_promises_map.end())
527529
return iter->second;

0 commit comments

Comments
 (0)