From d1a7a37c22c9a716818f76c7edd1a657bda0f441 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Wed, 31 Jan 2018 13:40:48 +0000 Subject: [clangd] Pass Context implicitly using TLS. Summary: Instead of passing Context explicitly around, we now have a thread-local Context object `Context::current()` which is an implicit argument to every function. Most manipulation of this should use the WithContextValue helper, which augments the current Context to add a single KV pair, and restores the old context on destruction. Advantages are: - less boilerplate in functions that just propagate contexts - reading most code doesn't require understanding context at all, and using context as values in fewer places still - fewer options to pass the "wrong" context when it changes within a scope (e.g. when using Span) - contexts pass through interfaces we can't modify, such as VFS - propagating contexts across threads was slightly tricky (e.g. copy vs move, no move-init in lambdas), and is now encapsulated in the threadpool Disadvantages are all the usual TLS stuff - hidden magic, and potential for higher memory usage on threads that don't use the context. (In practice, it's just one pointer) Reviewers: ilya-biryukov Subscribers: klimek, jkorous-apple, ioeric, cfe-commits Differential Revision: https://reviews.llvm.org/D42517 llvm-svn: 323872 --- clang-tools-extra/clangd/CodeComplete.cpp | 57 ++++++++++++++----------------- 1 file changed, 25 insertions(+), 32 deletions(-) (limited to 'clang-tools-extra/clangd/CodeComplete.cpp') diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 66e8a475918..498c6ca47ac 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -633,12 +633,11 @@ struct SemaCompleteInput { // Invokes Sema code completion on a file. // Callback will be invoked once completion is done, but before cleaning up. -bool semaCodeComplete(const Context &Ctx, - std::unique_ptr Consumer, +bool semaCodeComplete(std::unique_ptr Consumer, const clang::CodeCompleteOptions &Options, const SemaCompleteInput &Input, llvm::function_ref Callback = nullptr) { - auto Tracer = llvm::make_unique(Ctx, "Sema completion"); + auto Tracer = llvm::make_unique("Sema completion"); std::vector ArgStrs; for (const auto &S : Input.Command.CommandLine) ArgStrs.push_back(S.c_str()); @@ -690,13 +689,12 @@ bool semaCodeComplete(const Context &Ctx, SyntaxOnlyAction Action; if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) { - log(Ctx, "BeginSourceFile() failed when running codeComplete for " + - Input.FileName); + log("BeginSourceFile() failed when running codeComplete for " + + Input.FileName); return false; } if (!Action.Execute()) { - log(Ctx, - "Execute() failed when running codeComplete for " + Input.FileName); + log("Execute() failed when running codeComplete for " + Input.FileName); return false; } Tracer.reset(); @@ -704,7 +702,7 @@ bool semaCodeComplete(const Context &Ctx, if (Callback) Callback(); - Tracer = llvm::make_unique(Ctx, "Sema completion cleanup"); + Tracer = llvm::make_unique("Sema completion cleanup"); Action.EndSourceFile(); return true; @@ -801,8 +799,6 @@ clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const { // This score is combined with the result quality score for the final score. // - TopN determines the results with the best score. class CodeCompleteFlow { - trace::Span Tracer; - const Context &Ctx; const CodeCompleteOptions &Opts; // Sema takes ownership of Recorder. Recorder is valid until Sema cleanup. std::unique_ptr RecorderOwner; @@ -813,21 +809,22 @@ class CodeCompleteFlow { public: // A CodeCompleteFlow object is only useful for calling run() exactly once. - CodeCompleteFlow(const Context &Ctx, const CodeCompleteOptions &Opts) - : Tracer(Ctx, "CodeCompleteFlow"), Ctx(Tracer.Ctx), Opts(Opts), - RecorderOwner(new CompletionRecorder(Opts)), Recorder(*RecorderOwner) {} + CodeCompleteFlow(const CodeCompleteOptions &Opts) + : Opts(Opts), RecorderOwner(new CompletionRecorder(Opts)), + Recorder(*RecorderOwner) {} CompletionList run(const SemaCompleteInput &SemaCCInput) && { + trace::Span Tracer("CodeCompleteFlow"); // We run Sema code completion first. It builds an AST and calculates: // - completion results based on the AST. These are saved for merging. // - partial identifier and context. We need these for the index query. CompletionList Output; - semaCodeComplete(Ctx, std::move(RecorderOwner), Opts.getClangCompleteOpts(), + semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(), SemaCCInput, [&] { if (Recorder.CCSema) Output = runWithSema(); else - log(Ctx, "Code complete: no Sema callback, 0 results"); + log("Code complete: no Sema callback, 0 results"); }); SPAN_ATTACH(Tracer, "sema_results", NSema); @@ -835,8 +832,7 @@ public: SPAN_ATTACH(Tracer, "merged_results", NBoth); SPAN_ATTACH(Tracer, "returned_results", Output.items.size()); SPAN_ATTACH(Tracer, "incomplete", Output.isIncomplete); - log(Ctx, - llvm::formatv("Code complete: {0} results from Sema, {1} from Index, " + log(llvm::formatv("Code complete: {0} results from Sema, {1} from Index, " "{2} matched, {3} returned{4}.", NSema, NIndex, NBoth, Output.items.size(), Output.isIncomplete ? " (incomplete)" : "")); @@ -871,7 +867,7 @@ private: SymbolSlab queryIndex() { if (!Opts.Index || !allowIndex(Recorder.CCContext.getKind())) return SymbolSlab(); - trace::Span Tracer(Ctx, "Query index"); + trace::Span Tracer("Query index"); SPAN_ATTACH(Tracer, "limit", Opts.Limit); SymbolSlab::Builder ResultsBuilder; @@ -882,15 +878,12 @@ private: Req.Query = Filter->pattern(); Req.Scopes = getQueryScopes(Recorder.CCContext, Recorder.CCSema->getSourceManager()); - log(Tracer.Ctx, - llvm::formatv("Code complete: fuzzyFind(\"{0}\", Scopes: [{1}]", + log(llvm::formatv("Code complete: fuzzyFind(\"{0}\", scopes=[{1}])", Req.Query, llvm::join(Req.Scopes.begin(), Req.Scopes.end(), ","))); // Run the query against the index. - Incomplete |= - !Opts.Index->fuzzyFind(Tracer.Ctx, Req, [&](const Symbol &Sym) { - ResultsBuilder.insert(Sym); - }); + Incomplete |= !Opts.Index->fuzzyFind( + Req, [&](const Symbol &Sym) { ResultsBuilder.insert(Sym); }); return std::move(ResultsBuilder).build(); } @@ -899,7 +892,7 @@ private: std::vector> mergeResults(const std::vector &SemaResults, const SymbolSlab &IndexResults) { - trace::Span Tracer(Ctx, "Merge and score results"); + trace::Span Tracer("Merge and score results"); // We only keep the best N results at any time, in "native" format. TopN Top(Opts.Limit == 0 ? TopN::Unbounded : Opts.Limit); llvm::DenseSet UsedIndexResults; @@ -960,18 +953,18 @@ private: } }; -CompletionList codeComplete(const Context &Ctx, PathRef FileName, +CompletionList codeComplete(PathRef FileName, const tooling::CompileCommand &Command, PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr VFS, std::shared_ptr PCHs, CodeCompleteOptions Opts) { - return CodeCompleteFlow(Ctx, Opts).run( + return CodeCompleteFlow(Opts).run( {FileName, Command, Preamble, Contents, Pos, VFS, PCHs}); } -SignatureHelp signatureHelp(const Context &Ctx, PathRef FileName, +SignatureHelp signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, @@ -983,10 +976,10 @@ SignatureHelp signatureHelp(const Context &Ctx, PathRef FileName, Options.IncludeMacros = false; Options.IncludeCodePatterns = false; Options.IncludeBriefComments = true; - semaCodeComplete( - Ctx, llvm::make_unique(Options, Result), Options, - {FileName, Command, Preamble, Contents, Pos, std::move(VFS), - std::move(PCHs)}); + semaCodeComplete(llvm::make_unique(Options, Result), + Options, + {FileName, Command, Preamble, Contents, Pos, std::move(VFS), + std::move(PCHs)}); return Result; } -- cgit v1.2.3