1 //===--- TUScheduler.cpp -----------------------------------------*-C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // TUScheduler manages a worker per active file. This ASTWorker processes 9 // updates (modifications to file contents) and reads (actions performed on 10 // preamble/AST) to the file. 11 // 12 // Each ASTWorker owns a dedicated thread to process updates and reads to the 13 // relevant file. Any request gets queued in FIFO order to be processed by that 14 // thread. 15 // 16 // An update request replaces current praser inputs to ensure any subsequent 17 // read sees the version of the file they were requested. It will also issue a 18 // build for new inputs. 19 // 20 // ASTWorker processes the file in two parts, a preamble and a main-file 21 // section. A preamble can be reused between multiple versions of the file until 22 // invalidated by a modification to a header, compile commands or modification 23 // to relevant part of the current file. Such a preamble is called compatible. 24 // An update is considered dead if no read was issued for that version and 25 // diagnostics weren't requested by client or could be generated for a later 26 // version of the file. ASTWorker eliminates such requests as they are 27 // redundant. 28 // 29 // In the presence of stale (non-compatible) preambles, ASTWorker won't publish 30 // diagnostics for update requests. Read requests will be served with ASTs build 31 // with stale preambles, unless the read is picky and requires a compatible 32 // preamble. In such cases it will block until new preamble is built. 33 // 34 // ASTWorker owns a PreambleThread for building preambles. If the preamble gets 35 // invalidated by an update request, a new build will be requested on 36 // PreambleThread. Since PreambleThread only receives requests for newer 37 // versions of the file, in case of multiple requests it will only build the 38 // last one and skip requests in between. Unless client force requested 39 // diagnostics(WantDiagnostics::Yes). 40 // 41 // When a new preamble is built, a "golden" AST is immediately built from that 42 // version of the file. This ensures diagnostics get updated even if the queue 43 // is full. 44 // 45 // Some read requests might just need preamble. Since preambles can be read 46 // concurrently, ASTWorker runs these requests on their own thread. These 47 // requests will receive latest build preamble, which might possibly be stale. 48 49 #include "TUScheduler.h" 50 #include "CompileCommands.h" 51 #include "Compiler.h" 52 #include "Diagnostics.h" 53 #include "GlobalCompilationDatabase.h" 54 #include "ParsedAST.h" 55 #include "Preamble.h" 56 #include "index/CanonicalIncludes.h" 57 #include "support/Cancellation.h" 58 #include "support/Context.h" 59 #include "support/Logger.h" 60 #include "support/MemoryTree.h" 61 #include "support/Path.h" 62 #include "support/ThreadCrashReporter.h" 63 #include "support/Threading.h" 64 #include "support/Trace.h" 65 #include "clang/Frontend/CompilerInvocation.h" 66 #include "clang/Tooling/CompilationDatabase.h" 67 #include "llvm/ADT/FunctionExtras.h" 68 #include "llvm/ADT/None.h" 69 #include "llvm/ADT/Optional.h" 70 #include "llvm/ADT/STLExtras.h" 71 #include "llvm/ADT/ScopeExit.h" 72 #include "llvm/ADT/SmallVector.h" 73 #include "llvm/ADT/StringExtras.h" 74 #include "llvm/ADT/StringRef.h" 75 #include "llvm/Support/Allocator.h" 76 #include "llvm/Support/Errc.h" 77 #include "llvm/Support/ErrorHandling.h" 78 #include "llvm/Support/FormatVariadic.h" 79 #include "llvm/Support/Path.h" 80 #include "llvm/Support/Threading.h" 81 #include "llvm/Support/raw_ostream.h" 82 #include <algorithm> 83 #include <atomic> 84 #include <chrono> 85 #include <condition_variable> 86 #include <functional> 87 #include <memory> 88 #include <mutex> 89 #include <queue> 90 #include <string> 91 #include <thread> 92 #include <type_traits> 93 #include <utility> 94 #include <vector> 95 96 namespace clang { 97 namespace clangd { 98 using std::chrono::steady_clock; 99 100 namespace { 101 // Tracks latency (in seconds) of FS operations done during a preamble build. 102 // build_type allows to split by expected VFS cache state (cold on first 103 // preamble, somewhat warm after that when building first preamble for new file, 104 // likely ~everything cached on preamble rebuild. 105 constexpr trace::Metric 106 PreambleBuildFilesystemLatency("preamble_fs_latency", 107 trace::Metric::Distribution, "build_type"); 108 // Tracks latency of FS operations done during a preamble build as a ratio of 109 // preamble build time. build_type is same as above. 110 constexpr trace::Metric PreambleBuildFilesystemLatencyRatio( 111 "preamble_fs_latency_ratio", trace::Metric::Distribution, "build_type"); 112 113 constexpr trace::Metric PreambleBuildSize("preamble_build_size", 114 trace::Metric::Distribution); 115 constexpr trace::Metric PreambleSerializedSize("preamble_serialized_size", 116 trace::Metric::Distribution); 117 118 void reportPreambleBuild(const PreambleBuildStats &Stats, 119 bool IsFirstPreamble) { 120 auto RecordWithLabel = [&Stats](llvm::StringRef Label) { 121 PreambleBuildFilesystemLatency.record(Stats.FileSystemTime, Label); 122 if (Stats.TotalBuildTime > 0) // Avoid division by zero. 123 PreambleBuildFilesystemLatencyRatio.record( 124 Stats.FileSystemTime / Stats.TotalBuildTime, Label); 125 }; 126 127 static llvm::once_flag OnceFlag; 128 llvm::call_once(OnceFlag, [&] { RecordWithLabel("first_build"); }); 129 RecordWithLabel(IsFirstPreamble ? "first_build_for_file" : "rebuild"); 130 131 PreambleBuildSize.record(Stats.BuildSize); 132 PreambleSerializedSize.record(Stats.SerializedSize); 133 } 134 135 class ASTWorker; 136 } // namespace 137 138 static clang::clangd::Key<std::string> FileBeingProcessed; 139 140 llvm::Optional<llvm::StringRef> TUScheduler::getFileBeingProcessedInContext() { 141 if (auto *File = Context::current().get(FileBeingProcessed)) 142 return llvm::StringRef(*File); 143 return None; 144 } 145 146 /// An LRU cache of idle ASTs. 147 /// Because we want to limit the overall number of these we retain, the cache 148 /// owns ASTs (and may evict them) while their workers are idle. 149 /// Workers borrow ASTs when active, and return them when done. 150 class TUScheduler::ASTCache { 151 public: 152 using Key = const ASTWorker *; 153 154 ASTCache(unsigned MaxRetainedASTs) : MaxRetainedASTs(MaxRetainedASTs) {} 155 156 /// Returns result of getUsedBytes() for the AST cached by \p K. 157 /// If no AST is cached, 0 is returned. 158 std::size_t getUsedBytes(Key K) { 159 std::lock_guard<std::mutex> Lock(Mut); 160 auto It = findByKey(K); 161 if (It == LRU.end() || !It->second) 162 return 0; 163 return It->second->getUsedBytes(); 164 } 165 166 /// Store the value in the pool, possibly removing the last used AST. 167 /// The value should not be in the pool when this function is called. 168 void put(Key K, std::unique_ptr<ParsedAST> V) { 169 std::unique_lock<std::mutex> Lock(Mut); 170 assert(findByKey(K) == LRU.end()); 171 172 LRU.insert(LRU.begin(), {K, std::move(V)}); 173 if (LRU.size() <= MaxRetainedASTs) 174 return; 175 // We're past the limit, remove the last element. 176 std::unique_ptr<ParsedAST> ForCleanup = std::move(LRU.back().second); 177 LRU.pop_back(); 178 // Run the expensive destructor outside the lock. 179 Lock.unlock(); 180 ForCleanup.reset(); 181 } 182 183 /// Returns the cached value for \p K, or llvm::None if the value is not in 184 /// the cache anymore. If nullptr was cached for \p K, this function will 185 /// return a null unique_ptr wrapped into an optional. 186 /// If \p AccessMetric is set records whether there was a hit or miss. 187 llvm::Optional<std::unique_ptr<ParsedAST>> 188 take(Key K, const trace::Metric *AccessMetric = nullptr) { 189 // Record metric after unlocking the mutex. 190 std::unique_lock<std::mutex> Lock(Mut); 191 auto Existing = findByKey(K); 192 if (Existing == LRU.end()) { 193 if (AccessMetric) 194 AccessMetric->record(1, "miss"); 195 return None; 196 } 197 if (AccessMetric) 198 AccessMetric->record(1, "hit"); 199 std::unique_ptr<ParsedAST> V = std::move(Existing->second); 200 LRU.erase(Existing); 201 // GCC 4.8 fails to compile `return V;`, as it tries to call the copy 202 // constructor of unique_ptr, so we call the move ctor explicitly to avoid 203 // this miscompile. 204 return llvm::Optional<std::unique_ptr<ParsedAST>>(std::move(V)); 205 } 206 207 private: 208 using KVPair = std::pair<Key, std::unique_ptr<ParsedAST>>; 209 210 std::vector<KVPair>::iterator findByKey(Key K) { 211 return llvm::find_if(LRU, [K](const KVPair &P) { return P.first == K; }); 212 } 213 214 std::mutex Mut; 215 unsigned MaxRetainedASTs; 216 /// Items sorted in LRU order, i.e. first item is the most recently accessed 217 /// one. 218 std::vector<KVPair> LRU; /* GUARDED_BY(Mut) */ 219 }; 220 221 /// A map from header files to an opened "proxy" file that includes them. 222 /// If you open the header, the compile command from the proxy file is used. 223 /// 224 /// This inclusion information could also naturally live in the index, but there 225 /// are advantages to using open files instead: 226 /// - it's easier to achieve a *stable* choice of proxy, which is important 227 /// to avoid invalidating the preamble 228 /// - context-sensitive flags for libraries with multiple configurations 229 /// (e.g. C++ stdlib sensitivity to -std version) 230 /// - predictable behavior, e.g. guarantees that go-to-def landing on a header 231 /// will have a suitable command available 232 /// - fewer scaling problems to solve (project include graphs are big!) 233 /// 234 /// Implementation details: 235 /// - We only record this for mainfiles where the command was trustworthy 236 /// (i.e. not inferred). This avoids a bad inference "infecting" other files. 237 /// - Once we've picked a proxy file for a header, we stick with it until the 238 /// proxy file is invalidated *and* a new candidate proxy file is built. 239 /// Switching proxies is expensive, as the compile flags will (probably) 240 /// change and therefore we'll end up rebuilding the header's preamble. 241 /// - We don't capture the actual compile command, but just the filename we 242 /// should query to get it. This avoids getting out of sync with the CDB. 243 /// 244 /// All methods are threadsafe. In practice, update() comes from preamble 245 /// threads, remove()s mostly from the main thread, and get() from ASTWorker. 246 /// Writes are rare and reads are cheap, so we don't expect much contention. 247 class TUScheduler::HeaderIncluderCache { 248 // We should be be a little careful how we store the include graph of open 249 // files, as each can have a large number of transitive headers. 250 // This representation is O(unique transitive source files). 251 llvm::BumpPtrAllocator Arena; 252 struct Association { 253 llvm::StringRef MainFile; 254 // Circular-linked-list of associations with the same mainFile. 255 // Null indicates that the mainfile was removed. 256 Association *Next; 257 }; 258 llvm::StringMap<Association, llvm::BumpPtrAllocator &> HeaderToMain; 259 llvm::StringMap<Association *, llvm::BumpPtrAllocator &> MainToFirst; 260 std::atomic<size_t> UsedBytes; // Updated after writes. 261 mutable std::mutex Mu; 262 263 void invalidate(Association *First) { 264 Association *Current = First; 265 do { 266 Association *Next = Current->Next; 267 Current->Next = nullptr; 268 Current = Next; 269 } while (Current != First); 270 } 271 272 // Create the circular list and return the head of it. 273 Association *associate(llvm::StringRef MainFile, 274 llvm::ArrayRef<std::string> Headers) { 275 Association *First = nullptr, *Prev = nullptr; 276 for (const std::string &Header : Headers) { 277 auto &Assoc = HeaderToMain[Header]; 278 if (Assoc.Next) 279 continue; // Already has a valid association. 280 281 Assoc.MainFile = MainFile; 282 Assoc.Next = Prev; 283 Prev = &Assoc; 284 if (!First) 285 First = &Assoc; 286 } 287 if (First) 288 First->Next = Prev; 289 return First; 290 } 291 292 void updateMemoryUsage() { 293 auto StringMapHeap = [](const auto &Map) { 294 // StringMap stores the hashtable on the heap. 295 // It contains pointers to the entries, and a hashcode for each. 296 return Map.getNumBuckets() * (sizeof(void *) + sizeof(unsigned)); 297 }; 298 size_t Usage = Arena.getTotalMemory() + StringMapHeap(MainToFirst) + 299 StringMapHeap(HeaderToMain) + sizeof(*this); 300 UsedBytes.store(Usage, std::memory_order_release); 301 } 302 303 public: 304 HeaderIncluderCache() : HeaderToMain(Arena), MainToFirst(Arena) { 305 updateMemoryUsage(); 306 } 307 308 // Associate each header with MainFile (unless already associated). 309 // Headers not in the list will have their associations removed. 310 void update(PathRef MainFile, llvm::ArrayRef<std::string> Headers) { 311 std::lock_guard<std::mutex> Lock(Mu); 312 auto It = MainToFirst.try_emplace(MainFile, nullptr); 313 Association *&First = It.first->second; 314 if (First) 315 invalidate(First); 316 First = associate(It.first->first(), Headers); 317 updateMemoryUsage(); 318 } 319 320 // Mark MainFile as gone. 321 // This will *not* disassociate headers with MainFile immediately, but they 322 // will be eligible for association with other files that get update()d. 323 void remove(PathRef MainFile) { 324 std::lock_guard<std::mutex> Lock(Mu); 325 Association *&First = MainToFirst[MainFile]; 326 if (First) { 327 invalidate(First); 328 First = nullptr; 329 } 330 // MainToFirst entry should stay alive, as Associations might be pointing at 331 // its key. 332 } 333 334 /// Get the mainfile associated with Header, or the empty string if none. 335 std::string get(PathRef Header) const { 336 std::lock_guard<std::mutex> Lock(Mu); 337 return HeaderToMain.lookup(Header).MainFile.str(); 338 } 339 340 size_t getUsedBytes() const { 341 return UsedBytes.load(std::memory_order_acquire); 342 } 343 }; 344 345 namespace { 346 347 bool isReliable(const tooling::CompileCommand &Cmd) { 348 return Cmd.Heuristic.empty(); 349 } 350 351 /// Threadsafe manager for updating a TUStatus and emitting it after each 352 /// update. 353 class SynchronizedTUStatus { 354 public: 355 SynchronizedTUStatus(PathRef FileName, ParsingCallbacks &Callbacks) 356 : FileName(FileName), Callbacks(Callbacks) {} 357 358 void update(llvm::function_ref<void(TUStatus &)> Mutator) { 359 std::lock_guard<std::mutex> Lock(StatusMu); 360 Mutator(Status); 361 emitStatusLocked(); 362 } 363 364 /// Prevents emitting of further updates. 365 void stop() { 366 std::lock_guard<std::mutex> Lock(StatusMu); 367 CanPublish = false; 368 } 369 370 private: 371 void emitStatusLocked() { 372 if (CanPublish) 373 Callbacks.onFileUpdated(FileName, Status); 374 } 375 376 const Path FileName; 377 378 std::mutex StatusMu; 379 TUStatus Status; 380 bool CanPublish = true; 381 ParsingCallbacks &Callbacks; 382 }; 383 384 // An attempt to acquire resources for a task using PreambleThrottler. 385 // Initially it is unsatisfied, it (hopefully) becomes satisfied later but may 386 // be destroyed before then. Destruction releases all resources. 387 class PreambleThrottlerRequest { 388 public: 389 // The condition variable is signalled when the request is satisfied. 390 PreambleThrottlerRequest(llvm::StringRef Filename, 391 PreambleThrottler *Throttler, 392 std::condition_variable &CV) 393 : Throttler(Throttler), Satisfied(Throttler == nullptr) { 394 // If there is no throttler, this dummy request is always satisfied. 395 if (!Throttler) 396 return; 397 ID = Throttler->acquire(Filename, [&] { 398 Satisfied.store(true, std::memory_order_release); 399 CV.notify_all(); 400 }); 401 } 402 403 bool satisfied() const { return Satisfied.load(std::memory_order_acquire); } 404 405 // When the request is destroyed: 406 // - if resources are not yet obtained, stop trying to get them. 407 // - if resources were obtained, release them. 408 ~PreambleThrottlerRequest() { 409 if (Throttler) 410 Throttler->release(ID); 411 } 412 413 private: 414 PreambleThrottler::RequestID ID; 415 PreambleThrottler *Throttler; 416 std::atomic<bool> Satisfied = {false}; 417 }; 418 419 /// Responsible for building preambles. Whenever the thread is idle and the 420 /// preamble is outdated, it starts to build a fresh preamble from the latest 421 /// inputs. If RunSync is true, preambles are built synchronously in update() 422 /// instead. 423 class PreambleThread { 424 public: 425 PreambleThread(llvm::StringRef FileName, ParsingCallbacks &Callbacks, 426 bool StorePreambleInMemory, bool RunSync, 427 PreambleThrottler *Throttler, SynchronizedTUStatus &Status, 428 TUScheduler::HeaderIncluderCache &HeaderIncluders, 429 ASTWorker &AW) 430 : FileName(FileName), Callbacks(Callbacks), 431 StoreInMemory(StorePreambleInMemory), RunSync(RunSync), 432 Throttler(Throttler), Status(Status), ASTPeer(AW), 433 HeaderIncluders(HeaderIncluders) {} 434 435 /// It isn't guaranteed that each requested version will be built. If there 436 /// are multiple update requests while building a preamble, only the last one 437 /// will be built. 438 void update(std::unique_ptr<CompilerInvocation> CI, ParseInputs PI, 439 std::vector<Diag> CIDiags, WantDiagnostics WantDiags) { 440 Request Req = {std::move(CI), std::move(PI), std::move(CIDiags), WantDiags, 441 Context::current().clone()}; 442 if (RunSync) { 443 build(std::move(Req)); 444 Status.update([](TUStatus &Status) { 445 Status.PreambleActivity = PreambleAction::Idle; 446 }); 447 return; 448 } 449 { 450 std::unique_lock<std::mutex> Lock(Mutex); 451 // If NextReq was requested with WantDiagnostics::Yes we cannot just drop 452 // that on the floor. Block until we start building it. This won't 453 // dead-lock as we are blocking the caller thread, while builds continue 454 // on preamble thread. 455 ReqCV.wait(Lock, [this] { 456 return !NextReq || NextReq->WantDiags != WantDiagnostics::Yes; 457 }); 458 NextReq = std::move(Req); 459 } 460 // Let the worker thread know there's a request, notify_one is safe as there 461 // should be a single worker thread waiting on it. 462 ReqCV.notify_all(); 463 } 464 465 void run() { 466 while (true) { 467 llvm::Optional<PreambleThrottlerRequest> Throttle; 468 { 469 std::unique_lock<std::mutex> Lock(Mutex); 470 assert(!CurrentReq && "Already processing a request?"); 471 // Wait until stop is called or there is a request. 472 ReqCV.wait(Lock, [&] { return NextReq || Done; }); 473 if (Done) 474 break; 475 476 Throttle.emplace(FileName, Throttler, ReqCV); 477 // If acquire succeeded synchronously, avoid status jitter. 478 if (!Throttle->satisfied()) 479 Status.update([&](TUStatus &Status) { 480 Status.PreambleActivity = PreambleAction::Queued; 481 }); 482 ReqCV.wait(Lock, [&] { return Throttle->satisfied() || Done; }); 483 if (Done) 484 break; 485 // While waiting for the throttler, the request may have been updated! 486 // That's fine though, there's still guaranteed to be some request. 487 488 CurrentReq = std::move(*NextReq); 489 NextReq.reset(); 490 } 491 492 { 493 WithContext Guard(std::move(CurrentReq->Ctx)); 494 // Note that we don't make use of the ContextProvider here. 495 // Preamble tasks are always scheduled by ASTWorker tasks, and we 496 // reuse the context/config that was created at that level. 497 498 // Build the preamble and let the waiters know about it. 499 build(std::move(*CurrentReq)); 500 } 501 // Releasing the throttle before destroying the request assists testing. 502 Throttle.reset(); 503 bool IsEmpty = false; 504 { 505 std::lock_guard<std::mutex> Lock(Mutex); 506 CurrentReq.reset(); 507 IsEmpty = !NextReq; 508 } 509 if (IsEmpty) { 510 // We don't perform this above, before waiting for a request to make 511 // tests more deterministic. As there can be a race between this thread 512 // and client thread(clangdserver). 513 Status.update([](TUStatus &Status) { 514 Status.PreambleActivity = PreambleAction::Idle; 515 }); 516 } 517 ReqCV.notify_all(); 518 } 519 dlog("Preamble worker for {0} stopped", FileName); 520 } 521 522 /// Signals the run loop to exit. 523 void stop() { 524 dlog("Preamble worker for {0} received stop", FileName); 525 { 526 std::lock_guard<std::mutex> Lock(Mutex); 527 Done = true; 528 NextReq.reset(); 529 } 530 // Let the worker thread know that it should stop. 531 ReqCV.notify_all(); 532 } 533 534 bool blockUntilIdle(Deadline Timeout) const { 535 std::unique_lock<std::mutex> Lock(Mutex); 536 return wait(Lock, ReqCV, Timeout, [&] { return !NextReq && !CurrentReq; }); 537 } 538 539 private: 540 /// Holds inputs required for building a preamble. CI is guaranteed to be 541 /// non-null. 542 struct Request { 543 std::unique_ptr<CompilerInvocation> CI; 544 ParseInputs Inputs; 545 std::vector<Diag> CIDiags; 546 WantDiagnostics WantDiags; 547 Context Ctx; 548 }; 549 550 bool isDone() { 551 std::lock_guard<std::mutex> Lock(Mutex); 552 return Done; 553 } 554 555 /// Builds a preamble for \p Req, might reuse LatestBuild if possible. 556 /// Notifies ASTWorker after build finishes. 557 void build(Request Req); 558 559 mutable std::mutex Mutex; 560 bool Done = false; /* GUARDED_BY(Mutex) */ 561 llvm::Optional<Request> NextReq; /* GUARDED_BY(Mutex) */ 562 llvm::Optional<Request> CurrentReq; /* GUARDED_BY(Mutex) */ 563 // Signaled whenever a thread populates NextReq or worker thread builds a 564 // Preamble. 565 mutable std::condition_variable ReqCV; /* GUARDED_BY(Mutex) */ 566 // Accessed only by preamble thread. 567 std::shared_ptr<const PreambleData> LatestBuild; 568 569 const Path FileName; 570 ParsingCallbacks &Callbacks; 571 const bool StoreInMemory; 572 const bool RunSync; 573 PreambleThrottler *Throttler; 574 575 SynchronizedTUStatus &Status; 576 ASTWorker &ASTPeer; 577 TUScheduler::HeaderIncluderCache &HeaderIncluders; 578 }; 579 580 class ASTWorkerHandle; 581 582 /// Owns one instance of the AST, schedules updates and reads of it. 583 /// Also responsible for building and providing access to the preamble. 584 /// Each ASTWorker processes the async requests sent to it on a separate 585 /// dedicated thread. 586 /// The ASTWorker that manages the AST is shared by both the processing thread 587 /// and the TUScheduler. The TUScheduler should discard an ASTWorker when 588 /// remove() is called, but its thread may be busy and we don't want to block. 589 /// So the workers are accessed via an ASTWorkerHandle. Destroying the handle 590 /// signals the worker to exit its run loop and gives up shared ownership of the 591 /// worker. 592 class ASTWorker { 593 friend class ASTWorkerHandle; 594 ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB, 595 TUScheduler::ASTCache &LRUCache, 596 TUScheduler::HeaderIncluderCache &HeaderIncluders, 597 Semaphore &Barrier, bool RunSync, const TUScheduler::Options &Opts, 598 ParsingCallbacks &Callbacks); 599 600 public: 601 /// Create a new ASTWorker and return a handle to it. 602 /// The processing thread is spawned using \p Tasks. However, when \p Tasks 603 /// is null, all requests will be processed on the calling thread 604 /// synchronously instead. \p Barrier is acquired when processing each 605 /// request, it is used to limit the number of actively running threads. 606 static ASTWorkerHandle 607 create(PathRef FileName, const GlobalCompilationDatabase &CDB, 608 TUScheduler::ASTCache &IdleASTs, 609 TUScheduler::HeaderIncluderCache &HeaderIncluders, 610 AsyncTaskRunner *Tasks, Semaphore &Barrier, 611 const TUScheduler::Options &Opts, ParsingCallbacks &Callbacks); 612 ~ASTWorker(); 613 614 void update(ParseInputs Inputs, WantDiagnostics, bool ContentChanged); 615 void 616 runWithAST(llvm::StringRef Name, 617 llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action, 618 TUScheduler::ASTActionInvalidation); 619 bool blockUntilIdle(Deadline Timeout) const; 620 621 std::shared_ptr<const PreambleData> getPossiblyStalePreamble( 622 std::shared_ptr<const ASTSignals> *ASTSignals = nullptr) const; 623 624 /// Used to inform ASTWorker about a new preamble build by PreambleThread. 625 /// Diagnostics are only published through this callback. This ensures they 626 /// are always for newer versions of the file, as the callback gets called in 627 /// the same order as update requests. 628 void updatePreamble(std::unique_ptr<CompilerInvocation> CI, ParseInputs PI, 629 std::shared_ptr<const PreambleData> Preamble, 630 std::vector<Diag> CIDiags, WantDiagnostics WantDiags); 631 632 /// Obtain a preamble reflecting all updates so far. Threadsafe. 633 /// It may be delivered immediately, or later on the worker thread. 634 void getCurrentPreamble( 635 llvm::unique_function<void(std::shared_ptr<const PreambleData>)>); 636 /// Returns compile command from the current file inputs. 637 tooling::CompileCommand getCurrentCompileCommand() const; 638 639 /// Wait for the first build of preamble to finish. Preamble itself can be 640 /// accessed via getPossiblyStalePreamble(). Note that this function will 641 /// return after an unsuccessful build of the preamble too, i.e. result of 642 /// getPossiblyStalePreamble() can be null even after this function returns. 643 void waitForFirstPreamble() const; 644 645 TUScheduler::FileStats stats() const; 646 bool isASTCached() const; 647 648 private: 649 // Details of an update request that are relevant to scheduling. 650 struct UpdateType { 651 // Do we want diagnostics from this version? 652 // If Yes, we must always build this version. 653 // If No, we only need to build this version if it's read. 654 // If Auto, we build if it's read or if the debounce expires. 655 WantDiagnostics Diagnostics; 656 // Did the main-file content of the document change? 657 // If so, we're allowed to cancel certain invalidated preceding reads. 658 bool ContentChanged; 659 }; 660 661 /// Publishes diagnostics for \p Inputs. It will build an AST or reuse the 662 /// cached one if applicable. Assumes LatestPreamble is compatible for \p 663 /// Inputs. 664 void generateDiagnostics(std::unique_ptr<CompilerInvocation> Invocation, 665 ParseInputs Inputs, std::vector<Diag> CIDiags); 666 667 void updateASTSignals(ParsedAST &AST); 668 669 // Must be called exactly once on processing thread. Will return after 670 // stop() is called on a separate thread and all pending requests are 671 // processed. 672 void run(); 673 /// Signal that run() should finish processing pending requests and exit. 674 void stop(); 675 676 /// Adds a new task to the end of the request queue. 677 void startTask(llvm::StringRef Name, llvm::unique_function<void()> Task, 678 llvm::Optional<UpdateType> Update, 679 TUScheduler::ASTActionInvalidation); 680 /// Runs a task synchronously. 681 void runTask(llvm::StringRef Name, llvm::function_ref<void()> Task); 682 683 /// Determines the next action to perform. 684 /// All actions that should never run are discarded. 685 /// Returns a deadline for the next action. If it's expired, run now. 686 /// scheduleLocked() is called again at the deadline, or if requests arrive. 687 Deadline scheduleLocked(); 688 /// Should the first task in the queue be skipped instead of run? 689 bool shouldSkipHeadLocked() const; 690 691 struct Request { 692 llvm::unique_function<void()> Action; 693 std::string Name; 694 steady_clock::time_point AddTime; 695 Context Ctx; 696 llvm::Optional<Context> QueueCtx; 697 llvm::Optional<UpdateType> Update; 698 TUScheduler::ASTActionInvalidation InvalidationPolicy; 699 Canceler Invalidate; 700 }; 701 702 /// Handles retention of ASTs. 703 TUScheduler::ASTCache &IdleASTs; 704 TUScheduler::HeaderIncluderCache &HeaderIncluders; 705 const bool RunSync; 706 /// Time to wait after an update to see whether another update obsoletes it. 707 const DebouncePolicy UpdateDebounce; 708 /// File that ASTWorker is responsible for. 709 const Path FileName; 710 /// Callback to create processing contexts for tasks. 711 const std::function<Context(llvm::StringRef)> ContextProvider; 712 const GlobalCompilationDatabase &CDB; 713 /// Callback invoked when preamble or main file AST is built. 714 ParsingCallbacks &Callbacks; 715 716 Semaphore &Barrier; 717 /// Whether the 'onMainAST' callback ran for the current FileInputs. 718 bool RanASTCallback = false; 719 /// Guards members used by both TUScheduler and the worker thread. 720 mutable std::mutex Mutex; 721 /// File inputs, currently being used by the worker. 722 /// Writes and reads from unknown threads are locked. Reads from the worker 723 /// thread are not locked, as it's the only writer. 724 ParseInputs FileInputs; /* GUARDED_BY(Mutex) */ 725 /// Times of recent AST rebuilds, used for UpdateDebounce computation. 726 llvm::SmallVector<DebouncePolicy::clock::duration> 727 RebuildTimes; /* GUARDED_BY(Mutex) */ 728 /// Set to true to signal run() to finish processing. 729 bool Done; /* GUARDED_BY(Mutex) */ 730 std::deque<Request> Requests; /* GUARDED_BY(Mutex) */ 731 llvm::Optional<Request> CurrentRequest; /* GUARDED_BY(Mutex) */ 732 /// Signalled whenever a new request has been scheduled or processing of a 733 /// request has completed. 734 mutable std::condition_variable RequestsCV; 735 std::shared_ptr<const ASTSignals> LatestASTSignals; /* GUARDED_BY(Mutex) */ 736 /// Latest build preamble for current TU. 737 /// None means no builds yet, null means there was an error while building. 738 /// Only written by ASTWorker's thread. 739 llvm::Optional<std::shared_ptr<const PreambleData>> LatestPreamble; 740 std::deque<Request> PreambleRequests; /* GUARDED_BY(Mutex) */ 741 /// Signaled whenever LatestPreamble changes state or there's a new 742 /// PreambleRequest. 743 mutable std::condition_variable PreambleCV; 744 /// Guards the callback that publishes results of AST-related computations 745 /// (diagnostics) and file statuses. 746 std::mutex PublishMu; 747 // Used to prevent remove document + add document races that lead to 748 // out-of-order callbacks for publishing results of onMainAST callback. 749 // 750 // The lifetime of the old/new ASTWorkers will overlap, but their handles 751 // don't. When the old handle is destroyed, the old worker will stop reporting 752 // any results to the user. 753 bool CanPublishResults = true; /* GUARDED_BY(PublishMu) */ 754 std::atomic<unsigned> ASTBuildCount = {0}; 755 std::atomic<unsigned> PreambleBuildCount = {0}; 756 757 SynchronizedTUStatus Status; 758 PreambleThread PreamblePeer; 759 }; 760 761 /// A smart-pointer-like class that points to an active ASTWorker. 762 /// In destructor, signals to the underlying ASTWorker that no new requests will 763 /// be sent and the processing loop may exit (after running all pending 764 /// requests). 765 class ASTWorkerHandle { 766 friend class ASTWorker; 767 ASTWorkerHandle(std::shared_ptr<ASTWorker> Worker) 768 : Worker(std::move(Worker)) { 769 assert(this->Worker); 770 } 771 772 public: 773 ASTWorkerHandle(const ASTWorkerHandle &) = delete; 774 ASTWorkerHandle &operator=(const ASTWorkerHandle &) = delete; 775 ASTWorkerHandle(ASTWorkerHandle &&) = default; 776 ASTWorkerHandle &operator=(ASTWorkerHandle &&) = default; 777 778 ~ASTWorkerHandle() { 779 if (Worker) 780 Worker->stop(); 781 } 782 783 ASTWorker &operator*() { 784 assert(Worker && "Handle was moved from"); 785 return *Worker; 786 } 787 788 ASTWorker *operator->() { 789 assert(Worker && "Handle was moved from"); 790 return Worker.get(); 791 } 792 793 /// Returns an owning reference to the underlying ASTWorker that can outlive 794 /// the ASTWorkerHandle. However, no new requests to an active ASTWorker can 795 /// be schedule via the returned reference, i.e. only reads of the preamble 796 /// are possible. 797 std::shared_ptr<const ASTWorker> lock() { return Worker; } 798 799 private: 800 std::shared_ptr<ASTWorker> Worker; 801 }; 802 803 ASTWorkerHandle 804 ASTWorker::create(PathRef FileName, const GlobalCompilationDatabase &CDB, 805 TUScheduler::ASTCache &IdleASTs, 806 TUScheduler::HeaderIncluderCache &HeaderIncluders, 807 AsyncTaskRunner *Tasks, Semaphore &Barrier, 808 const TUScheduler::Options &Opts, 809 ParsingCallbacks &Callbacks) { 810 std::shared_ptr<ASTWorker> Worker( 811 new ASTWorker(FileName, CDB, IdleASTs, HeaderIncluders, Barrier, 812 /*RunSync=*/!Tasks, Opts, Callbacks)); 813 if (Tasks) { 814 Tasks->runAsync("ASTWorker:" + llvm::sys::path::filename(FileName), 815 [Worker]() { Worker->run(); }); 816 Tasks->runAsync("PreambleWorker:" + llvm::sys::path::filename(FileName), 817 [Worker]() { Worker->PreamblePeer.run(); }); 818 } 819 820 return ASTWorkerHandle(std::move(Worker)); 821 } 822 823 ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB, 824 TUScheduler::ASTCache &LRUCache, 825 TUScheduler::HeaderIncluderCache &HeaderIncluders, 826 Semaphore &Barrier, bool RunSync, 827 const TUScheduler::Options &Opts, 828 ParsingCallbacks &Callbacks) 829 : IdleASTs(LRUCache), HeaderIncluders(HeaderIncluders), RunSync(RunSync), 830 UpdateDebounce(Opts.UpdateDebounce), FileName(FileName), 831 ContextProvider(Opts.ContextProvider), CDB(CDB), Callbacks(Callbacks), 832 Barrier(Barrier), Done(false), Status(FileName, Callbacks), 833 PreamblePeer(FileName, Callbacks, Opts.StorePreamblesInMemory, RunSync, 834 Opts.PreambleThrottler, Status, HeaderIncluders, *this) { 835 // Set a fallback command because compile command can be accessed before 836 // `Inputs` is initialized. Other fields are only used after initialization 837 // from client inputs. 838 FileInputs.CompileCommand = CDB.getFallbackCommand(FileName); 839 } 840 841 ASTWorker::~ASTWorker() { 842 // Make sure we remove the cached AST, if any. 843 IdleASTs.take(this); 844 #ifndef NDEBUG 845 std::lock_guard<std::mutex> Lock(Mutex); 846 assert(Done && "handle was not destroyed"); 847 assert(Requests.empty() && !CurrentRequest && 848 "unprocessed requests when destroying ASTWorker"); 849 #endif 850 } 851 852 void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags, 853 bool ContentChanged) { 854 llvm::StringLiteral TaskName = "Update"; 855 auto Task = [=]() mutable { 856 // Get the actual command as `Inputs` does not have a command. 857 // FIXME: some build systems like Bazel will take time to preparing 858 // environment to build the file, it would be nice if we could emit a 859 // "PreparingBuild" status to inform users, it is non-trivial given the 860 // current implementation. 861 auto Cmd = CDB.getCompileCommand(FileName); 862 // If we don't have a reliable command for this file, it may be a header. 863 // Try to find a file that includes it, to borrow its command. 864 if (!Cmd || !isReliable(*Cmd)) { 865 std::string ProxyFile = HeaderIncluders.get(FileName); 866 if (!ProxyFile.empty()) { 867 auto ProxyCmd = CDB.getCompileCommand(ProxyFile); 868 if (!ProxyCmd || !isReliable(*ProxyCmd)) { 869 // This command is supposed to be reliable! It's probably gone. 870 HeaderIncluders.remove(ProxyFile); 871 } else { 872 // We have a reliable command for an including file, use it. 873 Cmd = tooling::transferCompileCommand(std::move(*ProxyCmd), FileName); 874 } 875 } 876 } 877 if (Cmd) 878 Inputs.CompileCommand = std::move(*Cmd); 879 else 880 Inputs.CompileCommand = CDB.getFallbackCommand(FileName); 881 882 bool InputsAreTheSame = 883 std::tie(FileInputs.CompileCommand, FileInputs.Contents) == 884 std::tie(Inputs.CompileCommand, Inputs.Contents); 885 // Cached AST is invalidated. 886 if (!InputsAreTheSame) { 887 IdleASTs.take(this); 888 RanASTCallback = false; 889 } 890 891 // Update current inputs so that subsequent reads can see them. 892 { 893 std::lock_guard<std::mutex> Lock(Mutex); 894 FileInputs = Inputs; 895 } 896 897 log("ASTWorker building file {0} version {1} with command {2}\n[{3}]\n{4}", 898 FileName, Inputs.Version, Inputs.CompileCommand.Heuristic, 899 Inputs.CompileCommand.Directory, 900 printArgv(Inputs.CompileCommand.CommandLine)); 901 902 StoreDiags CompilerInvocationDiagConsumer; 903 std::vector<std::string> CC1Args; 904 std::unique_ptr<CompilerInvocation> Invocation = buildCompilerInvocation( 905 Inputs, CompilerInvocationDiagConsumer, &CC1Args); 906 // Log cc1 args even (especially!) if creating invocation failed. 907 if (!CC1Args.empty()) 908 vlog("Driver produced command: cc1 {0}", printArgv(CC1Args)); 909 std::vector<Diag> CompilerInvocationDiags = 910 CompilerInvocationDiagConsumer.take(); 911 if (!Invocation) { 912 elog("Could not build CompilerInvocation for file {0}", FileName); 913 // Remove the old AST if it's still in cache. 914 IdleASTs.take(this); 915 RanASTCallback = false; 916 // Report the diagnostics we collected when parsing the command line. 917 Callbacks.onFailedAST(FileName, Inputs.Version, 918 std::move(CompilerInvocationDiags), 919 [&](llvm::function_ref<void()> Publish) { 920 // Ensure we only publish results from the worker 921 // if the file was not removed, making sure there 922 // are not race conditions. 923 std::lock_guard<std::mutex> Lock(PublishMu); 924 if (CanPublishResults) 925 Publish(); 926 }); 927 // Note that this might throw away a stale preamble that might still be 928 // useful, but this is how we communicate a build error. 929 LatestPreamble.emplace(); 930 // Make sure anyone waiting for the preamble gets notified it could not be 931 // built. 932 PreambleCV.notify_all(); 933 return; 934 } 935 936 PreamblePeer.update(std::move(Invocation), std::move(Inputs), 937 std::move(CompilerInvocationDiags), WantDiags); 938 std::unique_lock<std::mutex> Lock(Mutex); 939 PreambleCV.wait(Lock, [this] { 940 // Block until we reiceve a preamble request, unless a preamble already 941 // exists, as patching an empty preamble would imply rebuilding it from 942 // scratch. 943 // We block here instead of the consumer to prevent any deadlocks. Since 944 // LatestPreamble is only populated by ASTWorker thread. 945 return LatestPreamble || !PreambleRequests.empty() || Done; 946 }); 947 }; 948 startTask(TaskName, std::move(Task), UpdateType{WantDiags, ContentChanged}, 949 TUScheduler::NoInvalidation); 950 } 951 952 void ASTWorker::runWithAST( 953 llvm::StringRef Name, 954 llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action, 955 TUScheduler::ASTActionInvalidation Invalidation) { 956 // Tracks ast cache accesses for read operations. 957 static constexpr trace::Metric ASTAccessForRead( 958 "ast_access_read", trace::Metric::Counter, "result"); 959 auto Task = [=, Action = std::move(Action)]() mutable { 960 if (auto Reason = isCancelled()) 961 return Action(llvm::make_error<CancelledError>(Reason)); 962 llvm::Optional<std::unique_ptr<ParsedAST>> AST = 963 IdleASTs.take(this, &ASTAccessForRead); 964 if (!AST) { 965 StoreDiags CompilerInvocationDiagConsumer; 966 std::unique_ptr<CompilerInvocation> Invocation = 967 buildCompilerInvocation(FileInputs, CompilerInvocationDiagConsumer); 968 // Try rebuilding the AST. 969 vlog("ASTWorker rebuilding evicted AST to run {0}: {1} version {2}", Name, 970 FileName, FileInputs.Version); 971 // FIXME: We might need to build a patched ast once preamble thread starts 972 // running async. Currently getPossiblyStalePreamble below will always 973 // return a compatible preamble as ASTWorker::update blocks. 974 llvm::Optional<ParsedAST> NewAST; 975 if (Invocation) { 976 NewAST = ParsedAST::build(FileName, FileInputs, std::move(Invocation), 977 CompilerInvocationDiagConsumer.take(), 978 getPossiblyStalePreamble()); 979 ++ASTBuildCount; 980 } 981 AST = NewAST ? std::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr; 982 } 983 // Make sure we put the AST back into the LRU cache. 984 auto _ = llvm::make_scope_exit( 985 [&AST, this]() { IdleASTs.put(this, std::move(*AST)); }); 986 // Run the user-provided action. 987 if (!*AST) 988 return Action(error(llvm::errc::invalid_argument, "invalid AST")); 989 vlog("ASTWorker running {0} on version {2} of {1}", Name, FileName, 990 FileInputs.Version); 991 Action(InputsAndAST{FileInputs, **AST}); 992 }; 993 startTask(Name, std::move(Task), /*Update=*/None, Invalidation); 994 } 995 996 /// To be called from ThreadCrashReporter's signal handler. 997 static void crashDumpCompileCommand(llvm::raw_ostream &OS, 998 const tooling::CompileCommand &Command) { 999 OS << " Filename: " << Command.Filename << "\n"; 1000 OS << " Directory: " << Command.Directory << "\n"; 1001 OS << " Command Line:"; 1002 for (auto &Arg : Command.CommandLine) { 1003 OS << " " << Arg; 1004 } 1005 OS << "\n"; 1006 } 1007 1008 /// To be called from ThreadCrashReporter's signal handler. 1009 static void crashDumpFileContents(llvm::raw_ostream &OS, 1010 const std::string &Contents) { 1011 // Avoid flooding the terminal with source code by default, but allow clients 1012 // to opt in. Use an env var to preserve backwards compatibility of the 1013 // command line interface, while allowing it to be set outside the clangd 1014 // launch site for more flexibility. 1015 if (getenv("CLANGD_CRASH_DUMP_SOURCE")) { 1016 OS << " Contents:\n"; 1017 OS << Contents << "\n"; 1018 } 1019 } 1020 1021 /// To be called from ThreadCrashReporter's signal handler. 1022 static void crashDumpParseInputs(llvm::raw_ostream &OS, 1023 const ParseInputs &FileInputs) { 1024 auto &Command = FileInputs.CompileCommand; 1025 crashDumpCompileCommand(OS, Command); 1026 OS << " Version: " << FileInputs.Version << "\n"; 1027 crashDumpFileContents(OS, FileInputs.Contents); 1028 } 1029 1030 void PreambleThread::build(Request Req) { 1031 assert(Req.CI && "Got preamble request with null compiler invocation"); 1032 const ParseInputs &Inputs = Req.Inputs; 1033 bool ReusedPreamble = false; 1034 1035 Status.update([&](TUStatus &Status) { 1036 Status.PreambleActivity = PreambleAction::Building; 1037 }); 1038 auto _ = llvm::make_scope_exit([this, &Req, &ReusedPreamble] { 1039 ASTPeer.updatePreamble(std::move(Req.CI), std::move(Req.Inputs), 1040 LatestBuild, std::move(Req.CIDiags), 1041 std::move(Req.WantDiags)); 1042 if (!ReusedPreamble) 1043 Callbacks.onPreamblePublished(FileName); 1044 }); 1045 1046 if (!LatestBuild || Inputs.ForceRebuild) { 1047 vlog("Building first preamble for {0} version {1}", FileName, 1048 Inputs.Version); 1049 } else if (isPreambleCompatible(*LatestBuild, Inputs, FileName, *Req.CI)) { 1050 vlog("Reusing preamble version {0} for version {1} of {2}", 1051 LatestBuild->Version, Inputs.Version, FileName); 1052 ReusedPreamble = true; 1053 return; 1054 } else { 1055 vlog("Rebuilding invalidated preamble for {0} version {1} (previous was " 1056 "version {2})", 1057 FileName, Inputs.Version, LatestBuild->Version); 1058 } 1059 1060 ThreadCrashReporter ScopedReporter([&Inputs]() { 1061 llvm::errs() << "Signalled while building preamble\n"; 1062 crashDumpParseInputs(llvm::errs(), Inputs); 1063 }); 1064 1065 PreambleBuildStats Stats; 1066 bool IsFirstPreamble = !LatestBuild; 1067 LatestBuild = clang::clangd::buildPreamble( 1068 FileName, *Req.CI, Inputs, StoreInMemory, 1069 [&](ASTContext &Ctx, Preprocessor &PP, 1070 const CanonicalIncludes &CanonIncludes) { 1071 Callbacks.onPreambleAST(FileName, Inputs.Version, *Req.CI, Ctx, PP, 1072 CanonIncludes); 1073 }, 1074 &Stats); 1075 if (!LatestBuild) 1076 return; 1077 reportPreambleBuild(Stats, IsFirstPreamble); 1078 if (isReliable(LatestBuild->CompileCommand)) 1079 HeaderIncluders.update(FileName, LatestBuild->Includes.allHeaders()); 1080 } 1081 1082 void ASTWorker::updatePreamble(std::unique_ptr<CompilerInvocation> CI, 1083 ParseInputs PI, 1084 std::shared_ptr<const PreambleData> Preamble, 1085 std::vector<Diag> CIDiags, 1086 WantDiagnostics WantDiags) { 1087 llvm::StringLiteral TaskName = "Build AST"; 1088 // Store preamble and build diagnostics with new preamble if requested. 1089 auto Task = [this, Preamble = std::move(Preamble), CI = std::move(CI), 1090 PI = std::move(PI), CIDiags = std::move(CIDiags), 1091 WantDiags = std::move(WantDiags)]() mutable { 1092 // Update the preamble inside ASTWorker queue to ensure atomicity. As a task 1093 // running inside ASTWorker assumes internals won't change until it 1094 // finishes. 1095 if (!LatestPreamble || Preamble != *LatestPreamble) { 1096 ++PreambleBuildCount; 1097 // Cached AST is no longer valid. 1098 IdleASTs.take(this); 1099 RanASTCallback = false; 1100 std::lock_guard<std::mutex> Lock(Mutex); 1101 // LatestPreamble might be the last reference to old preamble, do not 1102 // trigger destructor while holding the lock. 1103 if (LatestPreamble) 1104 std::swap(*LatestPreamble, Preamble); 1105 else 1106 LatestPreamble = std::move(Preamble); 1107 } 1108 // Notify anyone waiting for a preamble. 1109 PreambleCV.notify_all(); 1110 // Give up our ownership to old preamble before starting expensive AST 1111 // build. 1112 Preamble.reset(); 1113 // We only need to build the AST if diagnostics were requested. 1114 if (WantDiags == WantDiagnostics::No) 1115 return; 1116 // Report diagnostics with the new preamble to ensure progress. Otherwise 1117 // diagnostics might get stale indefinitely if user keeps invalidating the 1118 // preamble. 1119 generateDiagnostics(std::move(CI), std::move(PI), std::move(CIDiags)); 1120 }; 1121 if (RunSync) { 1122 runTask(TaskName, Task); 1123 return; 1124 } 1125 { 1126 std::lock_guard<std::mutex> Lock(Mutex); 1127 PreambleRequests.push_back({std::move(Task), std::string(TaskName), 1128 steady_clock::now(), Context::current().clone(), 1129 llvm::None, llvm::None, 1130 TUScheduler::NoInvalidation, nullptr}); 1131 } 1132 PreambleCV.notify_all(); 1133 RequestsCV.notify_all(); 1134 } 1135 1136 void ASTWorker::updateASTSignals(ParsedAST &AST) { 1137 auto Signals = std::make_shared<const ASTSignals>(ASTSignals::derive(AST)); 1138 // Existing readers of ASTSignals will have their copy preserved until the 1139 // read is completed. The last reader deletes the old ASTSignals. 1140 { 1141 std::lock_guard<std::mutex> Lock(Mutex); 1142 std::swap(LatestASTSignals, Signals); 1143 } 1144 } 1145 1146 void ASTWorker::generateDiagnostics( 1147 std::unique_ptr<CompilerInvocation> Invocation, ParseInputs Inputs, 1148 std::vector<Diag> CIDiags) { 1149 // Tracks ast cache accesses for publishing diags. 1150 static constexpr trace::Metric ASTAccessForDiag( 1151 "ast_access_diag", trace::Metric::Counter, "result"); 1152 assert(Invocation); 1153 assert(LatestPreamble); 1154 // No need to rebuild the AST if we won't send the diagnostics. 1155 { 1156 std::lock_guard<std::mutex> Lock(PublishMu); 1157 if (!CanPublishResults) 1158 return; 1159 } 1160 // Used to check whether we can update AST cache. 1161 bool InputsAreLatest = 1162 std::tie(FileInputs.CompileCommand, FileInputs.Contents) == 1163 std::tie(Inputs.CompileCommand, Inputs.Contents); 1164 // Take a shortcut and don't report the diagnostics, since they should be the 1165 // same. All the clients should handle the lack of OnUpdated() call anyway to 1166 // handle empty result from buildAST. 1167 // FIXME: the AST could actually change if non-preamble includes changed, 1168 // but we choose to ignore it. 1169 if (InputsAreLatest && RanASTCallback) 1170 return; 1171 1172 // Get the AST for diagnostics, either build it or use the cached one. 1173 std::string TaskName = llvm::formatv("Build AST ({0})", Inputs.Version); 1174 Status.update([&](TUStatus &Status) { 1175 Status.ASTActivity.K = ASTAction::Building; 1176 Status.ASTActivity.Name = std::move(TaskName); 1177 }); 1178 // We might be able to reuse the last we've built for a read request. 1179 // FIXME: It might be better to not reuse this AST. That way queued AST builds 1180 // won't be required for diags. 1181 llvm::Optional<std::unique_ptr<ParsedAST>> AST = 1182 IdleASTs.take(this, &ASTAccessForDiag); 1183 if (!AST || !InputsAreLatest) { 1184 auto RebuildStartTime = DebouncePolicy::clock::now(); 1185 llvm::Optional<ParsedAST> NewAST = ParsedAST::build( 1186 FileName, Inputs, std::move(Invocation), CIDiags, *LatestPreamble); 1187 auto RebuildDuration = DebouncePolicy::clock::now() - RebuildStartTime; 1188 ++ASTBuildCount; 1189 // Try to record the AST-build time, to inform future update debouncing. 1190 // This is best-effort only: if the lock is held, don't bother. 1191 std::unique_lock<std::mutex> Lock(Mutex, std::try_to_lock); 1192 if (Lock.owns_lock()) { 1193 // Do not let RebuildTimes grow beyond its small-size (i.e. 1194 // capacity). 1195 if (RebuildTimes.size() == RebuildTimes.capacity()) 1196 RebuildTimes.erase(RebuildTimes.begin()); 1197 RebuildTimes.push_back(RebuildDuration); 1198 Lock.unlock(); 1199 } 1200 Status.update([&](TUStatus &Status) { 1201 Status.Details.ReuseAST = false; 1202 Status.Details.BuildFailed = !NewAST; 1203 }); 1204 AST = NewAST ? std::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr; 1205 } else { 1206 log("Skipping rebuild of the AST for {0}, inputs are the same.", FileName); 1207 Status.update([](TUStatus &Status) { 1208 Status.Details.ReuseAST = true; 1209 Status.Details.BuildFailed = false; 1210 }); 1211 } 1212 1213 // Publish diagnostics. 1214 auto RunPublish = [&](llvm::function_ref<void()> Publish) { 1215 // Ensure we only publish results from the worker if the file was not 1216 // removed, making sure there are not race conditions. 1217 std::lock_guard<std::mutex> Lock(PublishMu); 1218 if (CanPublishResults) 1219 Publish(); 1220 }; 1221 if (*AST) { 1222 trace::Span Span("Running main AST callback"); 1223 Callbacks.onMainAST(FileName, **AST, RunPublish); 1224 updateASTSignals(**AST); 1225 } else { 1226 // Failed to build the AST, at least report diagnostics from the 1227 // command line if there were any. 1228 // FIXME: we might have got more errors while trying to build the 1229 // AST, surface them too. 1230 Callbacks.onFailedAST(FileName, Inputs.Version, CIDiags, RunPublish); 1231 } 1232 1233 // AST might've been built for an older version of the source, as ASTWorker 1234 // queue raced ahead while we were waiting on the preamble. In that case the 1235 // queue can't reuse the AST. 1236 if (InputsAreLatest) { 1237 RanASTCallback = *AST != nullptr; 1238 IdleASTs.put(this, std::move(*AST)); 1239 } 1240 } 1241 1242 std::shared_ptr<const PreambleData> ASTWorker::getPossiblyStalePreamble( 1243 std::shared_ptr<const ASTSignals> *ASTSignals) const { 1244 std::lock_guard<std::mutex> Lock(Mutex); 1245 if (ASTSignals) 1246 *ASTSignals = LatestASTSignals; 1247 return LatestPreamble ? *LatestPreamble : nullptr; 1248 } 1249 1250 void ASTWorker::waitForFirstPreamble() const { 1251 std::unique_lock<std::mutex> Lock(Mutex); 1252 PreambleCV.wait(Lock, [this] { return LatestPreamble || Done; }); 1253 } 1254 1255 tooling::CompileCommand ASTWorker::getCurrentCompileCommand() const { 1256 std::unique_lock<std::mutex> Lock(Mutex); 1257 return FileInputs.CompileCommand; 1258 } 1259 1260 TUScheduler::FileStats ASTWorker::stats() const { 1261 TUScheduler::FileStats Result; 1262 Result.ASTBuilds = ASTBuildCount; 1263 Result.PreambleBuilds = PreambleBuildCount; 1264 // Note that we don't report the size of ASTs currently used for processing 1265 // the in-flight requests. We used this information for debugging purposes 1266 // only, so this should be fine. 1267 Result.UsedBytesAST = IdleASTs.getUsedBytes(this); 1268 if (auto Preamble = getPossiblyStalePreamble()) 1269 Result.UsedBytesPreamble = Preamble->Preamble.getSize(); 1270 return Result; 1271 } 1272 1273 bool ASTWorker::isASTCached() const { return IdleASTs.getUsedBytes(this) != 0; } 1274 1275 void ASTWorker::stop() { 1276 { 1277 std::lock_guard<std::mutex> Lock(PublishMu); 1278 CanPublishResults = false; 1279 } 1280 { 1281 std::lock_guard<std::mutex> Lock(Mutex); 1282 assert(!Done && "stop() called twice"); 1283 Done = true; 1284 } 1285 PreamblePeer.stop(); 1286 // We are no longer going to build any preambles, let the waiters know that. 1287 PreambleCV.notify_all(); 1288 Status.stop(); 1289 RequestsCV.notify_all(); 1290 } 1291 1292 void ASTWorker::runTask(llvm::StringRef Name, llvm::function_ref<void()> Task) { 1293 ThreadCrashReporter ScopedReporter([this, Name]() { 1294 llvm::errs() << "Signalled during AST worker action: " << Name << "\n"; 1295 crashDumpParseInputs(llvm::errs(), FileInputs); 1296 }); 1297 trace::Span Tracer(Name); 1298 WithContext WithProvidedContext(ContextProvider(FileName)); 1299 Task(); 1300 } 1301 1302 void ASTWorker::startTask(llvm::StringRef Name, 1303 llvm::unique_function<void()> Task, 1304 llvm::Optional<UpdateType> Update, 1305 TUScheduler::ASTActionInvalidation Invalidation) { 1306 if (RunSync) { 1307 assert(!Done && "running a task after stop()"); 1308 runTask(Name, Task); 1309 return; 1310 } 1311 1312 { 1313 std::lock_guard<std::mutex> Lock(Mutex); 1314 assert(!Done && "running a task after stop()"); 1315 // Cancel any requests invalidated by this request. 1316 if (Update && Update->ContentChanged) { 1317 for (auto &R : llvm::reverse(Requests)) { 1318 if (R.InvalidationPolicy == TUScheduler::InvalidateOnUpdate) 1319 R.Invalidate(); 1320 if (R.Update && R.Update->ContentChanged) 1321 break; // Older requests were already invalidated by the older update. 1322 } 1323 } 1324 1325 // Allow this request to be cancelled if invalidated. 1326 Context Ctx = Context::current().derive(FileBeingProcessed, FileName); 1327 Canceler Invalidate = nullptr; 1328 if (Invalidation) { 1329 WithContext WC(std::move(Ctx)); 1330 std::tie(Ctx, Invalidate) = cancelableTask( 1331 /*Reason=*/static_cast<int>(ErrorCode::ContentModified)); 1332 } 1333 // Trace the time the request spends in the queue, and the requests that 1334 // it's going to wait for. 1335 llvm::Optional<Context> QueueCtx; 1336 if (trace::enabled()) { 1337 // Tracers that follow threads and need strict nesting will see a tiny 1338 // instantaneous event "we're enqueueing", and sometime later it runs. 1339 WithContext WC(Ctx.clone()); 1340 trace::Span Tracer("Queued:" + Name); 1341 if (Tracer.Args) { 1342 if (CurrentRequest) 1343 SPAN_ATTACH(Tracer, "CurrentRequest", CurrentRequest->Name); 1344 llvm::json::Array PreambleRequestsNames; 1345 for (const auto &Req : PreambleRequests) 1346 PreambleRequestsNames.push_back(Req.Name); 1347 SPAN_ATTACH(Tracer, "PreambleRequestsNames", 1348 std::move(PreambleRequestsNames)); 1349 llvm::json::Array RequestsNames; 1350 for (const auto &Req : Requests) 1351 RequestsNames.push_back(Req.Name); 1352 SPAN_ATTACH(Tracer, "RequestsNames", std::move(RequestsNames)); 1353 } 1354 // For tracers that follow contexts, keep the trace span's context alive 1355 // until we dequeue the request, so they see the full duration. 1356 QueueCtx = Context::current().clone(); 1357 } 1358 Requests.push_back({std::move(Task), std::string(Name), steady_clock::now(), 1359 std::move(Ctx), std::move(QueueCtx), Update, 1360 Invalidation, std::move(Invalidate)}); 1361 } 1362 RequestsCV.notify_all(); 1363 } 1364 1365 void ASTWorker::run() { 1366 while (true) { 1367 { 1368 std::unique_lock<std::mutex> Lock(Mutex); 1369 assert(!CurrentRequest && "A task is already running, multiple workers?"); 1370 for (auto Wait = scheduleLocked(); !Wait.expired(); 1371 Wait = scheduleLocked()) { 1372 assert(PreambleRequests.empty() && 1373 "Preamble updates should be scheduled immediately"); 1374 if (Done) { 1375 if (Requests.empty()) 1376 return; 1377 // Even though Done is set, finish pending requests. 1378 break; // However, skip delays to shutdown fast. 1379 } 1380 1381 // Tracing: we have a next request, attribute this sleep to it. 1382 llvm::Optional<WithContext> Ctx; 1383 llvm::Optional<trace::Span> Tracer; 1384 if (!Requests.empty()) { 1385 Ctx.emplace(Requests.front().Ctx.clone()); 1386 Tracer.emplace("Debounce"); 1387 SPAN_ATTACH(*Tracer, "next_request", Requests.front().Name); 1388 if (!(Wait == Deadline::infinity())) { 1389 Status.update([&](TUStatus &Status) { 1390 Status.ASTActivity.K = ASTAction::Queued; 1391 Status.ASTActivity.Name = Requests.front().Name; 1392 }); 1393 SPAN_ATTACH(*Tracer, "sleep_ms", 1394 std::chrono::duration_cast<std::chrono::milliseconds>( 1395 Wait.time() - steady_clock::now()) 1396 .count()); 1397 } 1398 } 1399 1400 wait(Lock, RequestsCV, Wait); 1401 } 1402 // Any request in ReceivedPreambles is at least as old as the 1403 // Requests.front(), so prefer them first to preserve LSP order. 1404 if (!PreambleRequests.empty()) { 1405 CurrentRequest = std::move(PreambleRequests.front()); 1406 PreambleRequests.pop_front(); 1407 } else { 1408 CurrentRequest = std::move(Requests.front()); 1409 Requests.pop_front(); 1410 } 1411 } // unlock Mutex 1412 1413 // Inform tracing that the request was dequeued. 1414 CurrentRequest->QueueCtx.reset(); 1415 1416 // It is safe to perform reads to CurrentRequest without holding the lock as 1417 // only writer is also this thread. 1418 { 1419 std::unique_lock<Semaphore> Lock(Barrier, std::try_to_lock); 1420 if (!Lock.owns_lock()) { 1421 Status.update([&](TUStatus &Status) { 1422 Status.ASTActivity.K = ASTAction::Queued; 1423 Status.ASTActivity.Name = CurrentRequest->Name; 1424 }); 1425 Lock.lock(); 1426 } 1427 WithContext Guard(std::move(CurrentRequest->Ctx)); 1428 Status.update([&](TUStatus &Status) { 1429 Status.ASTActivity.K = ASTAction::RunningAction; 1430 Status.ASTActivity.Name = CurrentRequest->Name; 1431 }); 1432 runTask(CurrentRequest->Name, CurrentRequest->Action); 1433 } 1434 1435 bool IsEmpty = false; 1436 { 1437 std::lock_guard<std::mutex> Lock(Mutex); 1438 CurrentRequest.reset(); 1439 IsEmpty = Requests.empty() && PreambleRequests.empty(); 1440 } 1441 if (IsEmpty) { 1442 Status.update([&](TUStatus &Status) { 1443 Status.ASTActivity.K = ASTAction::Idle; 1444 Status.ASTActivity.Name = ""; 1445 }); 1446 } 1447 RequestsCV.notify_all(); 1448 } 1449 } 1450 1451 Deadline ASTWorker::scheduleLocked() { 1452 // Process new preambles immediately. 1453 if (!PreambleRequests.empty()) 1454 return Deadline::zero(); 1455 if (Requests.empty()) 1456 return Deadline::infinity(); // Wait for new requests. 1457 // Handle cancelled requests first so the rest of the scheduler doesn't. 1458 for (auto I = Requests.begin(), E = Requests.end(); I != E; ++I) { 1459 if (!isCancelled(I->Ctx)) { 1460 // Cancellations after the first read don't affect current scheduling. 1461 if (I->Update == None) 1462 break; 1463 continue; 1464 } 1465 // Cancelled reads are moved to the front of the queue and run immediately. 1466 if (I->Update == None) { 1467 Request R = std::move(*I); 1468 Requests.erase(I); 1469 Requests.push_front(std::move(R)); 1470 return Deadline::zero(); 1471 } 1472 // Cancelled updates are downgraded to auto-diagnostics, and may be elided. 1473 if (I->Update->Diagnostics == WantDiagnostics::Yes) 1474 I->Update->Diagnostics = WantDiagnostics::Auto; 1475 } 1476 1477 while (shouldSkipHeadLocked()) { 1478 vlog("ASTWorker skipping {0} for {1}", Requests.front().Name, FileName); 1479 Requests.pop_front(); 1480 } 1481 assert(!Requests.empty() && "skipped the whole queue"); 1482 // Some updates aren't dead yet, but never end up being used. 1483 // e.g. the first keystroke is live until obsoleted by the second. 1484 // We debounce "maybe-unused" writes, sleeping in case they become dead. 1485 // But don't delay reads (including updates where diagnostics are needed). 1486 for (const auto &R : Requests) 1487 if (R.Update == None || R.Update->Diagnostics == WantDiagnostics::Yes) 1488 return Deadline::zero(); 1489 // Front request needs to be debounced, so determine when we're ready. 1490 Deadline D(Requests.front().AddTime + UpdateDebounce.compute(RebuildTimes)); 1491 return D; 1492 } 1493 1494 // Returns true if Requests.front() is a dead update that can be skipped. 1495 bool ASTWorker::shouldSkipHeadLocked() const { 1496 assert(!Requests.empty()); 1497 auto Next = Requests.begin(); 1498 auto Update = Next->Update; 1499 if (!Update) // Only skip updates. 1500 return false; 1501 ++Next; 1502 // An update is live if its AST might still be read. 1503 // That is, if it's not immediately followed by another update. 1504 if (Next == Requests.end() || !Next->Update) 1505 return false; 1506 // The other way an update can be live is if its diagnostics might be used. 1507 switch (Update->Diagnostics) { 1508 case WantDiagnostics::Yes: 1509 return false; // Always used. 1510 case WantDiagnostics::No: 1511 return true; // Always dead. 1512 case WantDiagnostics::Auto: 1513 // Used unless followed by an update that generates diagnostics. 1514 for (; Next != Requests.end(); ++Next) 1515 if (Next->Update && Next->Update->Diagnostics != WantDiagnostics::No) 1516 return true; // Prefer later diagnostics. 1517 return false; 1518 } 1519 llvm_unreachable("Unknown WantDiagnostics"); 1520 } 1521 1522 bool ASTWorker::blockUntilIdle(Deadline Timeout) const { 1523 auto WaitUntilASTWorkerIsIdle = [&] { 1524 std::unique_lock<std::mutex> Lock(Mutex); 1525 return wait(Lock, RequestsCV, Timeout, [&] { 1526 return PreambleRequests.empty() && Requests.empty() && !CurrentRequest; 1527 }); 1528 }; 1529 // Make sure ASTWorker has processed all requests, which might issue new 1530 // updates to PreamblePeer. 1531 if (!WaitUntilASTWorkerIsIdle()) 1532 return false; 1533 // Now that ASTWorker processed all requests, ensure PreamblePeer has served 1534 // all update requests. This might create new PreambleRequests for the 1535 // ASTWorker. 1536 if (!PreamblePeer.blockUntilIdle(Timeout)) 1537 return false; 1538 assert(Requests.empty() && 1539 "No new normal tasks can be scheduled concurrently with " 1540 "blockUntilIdle(): ASTWorker isn't threadsafe"); 1541 // Finally make sure ASTWorker has processed all of the preamble updates. 1542 return WaitUntilASTWorkerIsIdle(); 1543 } 1544 1545 // Render a TUAction to a user-facing string representation. 1546 // TUAction represents clangd-internal states, we don't intend to expose them 1547 // to users (say C++ programmers) directly to avoid confusion, we use terms that 1548 // are familiar by C++ programmers. 1549 std::string renderTUAction(const PreambleAction PA, const ASTAction &AA) { 1550 llvm::SmallVector<std::string, 2> Result; 1551 switch (PA) { 1552 case PreambleAction::Building: 1553 Result.push_back("parsing includes"); 1554 break; 1555 case PreambleAction::Queued: 1556 Result.push_back("includes are queued"); 1557 break; 1558 case PreambleAction::Idle: 1559 // We handle idle specially below. 1560 break; 1561 } 1562 switch (AA.K) { 1563 case ASTAction::Queued: 1564 Result.push_back("file is queued"); 1565 break; 1566 case ASTAction::RunningAction: 1567 Result.push_back("running " + AA.Name); 1568 break; 1569 case ASTAction::Building: 1570 Result.push_back("parsing main file"); 1571 break; 1572 case ASTAction::Idle: 1573 // We handle idle specially below. 1574 break; 1575 } 1576 if (Result.empty()) 1577 return "idle"; 1578 return llvm::join(Result, ", "); 1579 } 1580 1581 } // namespace 1582 1583 unsigned getDefaultAsyncThreadsCount() { 1584 return llvm::heavyweight_hardware_concurrency().compute_thread_count(); 1585 } 1586 1587 FileStatus TUStatus::render(PathRef File) const { 1588 FileStatus FStatus; 1589 FStatus.uri = URIForFile::canonicalize(File, /*TUPath=*/File); 1590 FStatus.state = renderTUAction(PreambleActivity, ASTActivity); 1591 return FStatus; 1592 } 1593 1594 struct TUScheduler::FileData { 1595 /// Latest inputs, passed to TUScheduler::update(). 1596 std::string Contents; 1597 ASTWorkerHandle Worker; 1598 }; 1599 1600 TUScheduler::TUScheduler(const GlobalCompilationDatabase &CDB, 1601 const Options &Opts, 1602 std::unique_ptr<ParsingCallbacks> Callbacks) 1603 : CDB(CDB), Opts(Opts), 1604 Callbacks(Callbacks ? std::move(Callbacks) 1605 : std::make_unique<ParsingCallbacks>()), 1606 Barrier(Opts.AsyncThreadsCount), QuickRunBarrier(Opts.AsyncThreadsCount), 1607 IdleASTs( 1608 std::make_unique<ASTCache>(Opts.RetentionPolicy.MaxRetainedASTs)), 1609 HeaderIncluders(std::make_unique<HeaderIncluderCache>()) { 1610 // Avoid null checks everywhere. 1611 if (!Opts.ContextProvider) { 1612 this->Opts.ContextProvider = [](llvm::StringRef) { 1613 return Context::current().clone(); 1614 }; 1615 } 1616 if (0 < Opts.AsyncThreadsCount) { 1617 PreambleTasks.emplace(); 1618 WorkerThreads.emplace(); 1619 } 1620 } 1621 1622 TUScheduler::~TUScheduler() { 1623 // Notify all workers that they need to stop. 1624 Files.clear(); 1625 1626 // Wait for all in-flight tasks to finish. 1627 if (PreambleTasks) 1628 PreambleTasks->wait(); 1629 if (WorkerThreads) 1630 WorkerThreads->wait(); 1631 } 1632 1633 bool TUScheduler::blockUntilIdle(Deadline D) const { 1634 for (auto &File : Files) 1635 if (!File.getValue()->Worker->blockUntilIdle(D)) 1636 return false; 1637 if (PreambleTasks) 1638 if (!PreambleTasks->wait(D)) 1639 return false; 1640 return true; 1641 } 1642 1643 bool TUScheduler::update(PathRef File, ParseInputs Inputs, 1644 WantDiagnostics WantDiags) { 1645 std::unique_ptr<FileData> &FD = Files[File]; 1646 bool NewFile = FD == nullptr; 1647 bool ContentChanged = false; 1648 if (!FD) { 1649 // Create a new worker to process the AST-related tasks. 1650 ASTWorkerHandle Worker = 1651 ASTWorker::create(File, CDB, *IdleASTs, *HeaderIncluders, 1652 WorkerThreads ? WorkerThreads.getPointer() : nullptr, 1653 Barrier, Opts, *Callbacks); 1654 FD = std::unique_ptr<FileData>( 1655 new FileData{Inputs.Contents, std::move(Worker)}); 1656 ContentChanged = true; 1657 } else if (FD->Contents != Inputs.Contents) { 1658 ContentChanged = true; 1659 FD->Contents = Inputs.Contents; 1660 } 1661 FD->Worker->update(std::move(Inputs), WantDiags, ContentChanged); 1662 // There might be synthetic update requests, don't change the LastActiveFile 1663 // in such cases. 1664 if (ContentChanged) 1665 LastActiveFile = File.str(); 1666 return NewFile; 1667 } 1668 1669 void TUScheduler::remove(PathRef File) { 1670 bool Removed = Files.erase(File); 1671 if (!Removed) 1672 elog("Trying to remove file from TUScheduler that is not tracked: {0}", 1673 File); 1674 // We don't call HeaderIncluders.remove(File) here. 1675 // If we did, we'd avoid potentially stale header/mainfile associations. 1676 // However, it would mean that closing a mainfile could invalidate the 1677 // preamble of several open headers. 1678 } 1679 1680 void TUScheduler::run(llvm::StringRef Name, llvm::StringRef Path, 1681 llvm::unique_function<void()> Action) { 1682 runWithSemaphore(Name, Path, std::move(Action), Barrier); 1683 } 1684 1685 void TUScheduler::runQuick(llvm::StringRef Name, llvm::StringRef Path, 1686 llvm::unique_function<void()> Action) { 1687 // Use QuickRunBarrier to serialize quick tasks: we are ignoring 1688 // the parallelism level set by the user, don't abuse it 1689 runWithSemaphore(Name, Path, std::move(Action), QuickRunBarrier); 1690 } 1691 1692 void TUScheduler::runWithSemaphore(llvm::StringRef Name, llvm::StringRef Path, 1693 llvm::unique_function<void()> Action, 1694 Semaphore &Sem) { 1695 if (Path.empty()) 1696 Path = LastActiveFile; 1697 else 1698 LastActiveFile = Path.str(); 1699 if (!PreambleTasks) { 1700 WithContext WithProvidedContext(Opts.ContextProvider(Path)); 1701 return Action(); 1702 } 1703 PreambleTasks->runAsync(Name, [this, &Sem, Ctx = Context::current().clone(), 1704 Path(Path.str()), 1705 Action = std::move(Action)]() mutable { 1706 std::lock_guard<Semaphore> BarrierLock(Sem); 1707 WithContext WC(std::move(Ctx)); 1708 WithContext WithProvidedContext(Opts.ContextProvider(Path)); 1709 Action(); 1710 }); 1711 } 1712 1713 void TUScheduler::runWithAST( 1714 llvm::StringRef Name, PathRef File, 1715 llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action, 1716 TUScheduler::ASTActionInvalidation Invalidation) { 1717 auto It = Files.find(File); 1718 if (It == Files.end()) { 1719 Action(llvm::make_error<LSPError>( 1720 "trying to get AST for non-added document", ErrorCode::InvalidParams)); 1721 return; 1722 } 1723 LastActiveFile = File.str(); 1724 1725 It->second->Worker->runWithAST(Name, std::move(Action), Invalidation); 1726 } 1727 1728 void TUScheduler::runWithPreamble(llvm::StringRef Name, PathRef File, 1729 PreambleConsistency Consistency, 1730 Callback<InputsAndPreamble> Action) { 1731 auto It = Files.find(File); 1732 if (It == Files.end()) { 1733 Action(llvm::make_error<LSPError>( 1734 "trying to get preamble for non-added document", 1735 ErrorCode::InvalidParams)); 1736 return; 1737 } 1738 LastActiveFile = File.str(); 1739 1740 if (!PreambleTasks) { 1741 trace::Span Tracer(Name); 1742 SPAN_ATTACH(Tracer, "file", File); 1743 std::shared_ptr<const ASTSignals> Signals; 1744 std::shared_ptr<const PreambleData> Preamble = 1745 It->second->Worker->getPossiblyStalePreamble(&Signals); 1746 WithContext WithProvidedContext(Opts.ContextProvider(File)); 1747 Action(InputsAndPreamble{It->second->Contents, 1748 It->second->Worker->getCurrentCompileCommand(), 1749 Preamble.get(), Signals.get()}); 1750 return; 1751 } 1752 1753 std::shared_ptr<const ASTWorker> Worker = It->second->Worker.lock(); 1754 auto Task = [Worker, Consistency, Name = Name.str(), File = File.str(), 1755 Contents = It->second->Contents, 1756 Command = Worker->getCurrentCompileCommand(), 1757 Ctx = Context::current().derive(FileBeingProcessed, 1758 std::string(File)), 1759 Action = std::move(Action), this]() mutable { 1760 ThreadCrashReporter ScopedReporter([&Name, &Contents, &Command]() { 1761 llvm::errs() << "Signalled during preamble action: " << Name << "\n"; 1762 crashDumpCompileCommand(llvm::errs(), Command); 1763 crashDumpFileContents(llvm::errs(), Contents); 1764 }); 1765 std::shared_ptr<const PreambleData> Preamble; 1766 if (Consistency == PreambleConsistency::Stale) { 1767 // Wait until the preamble is built for the first time, if preamble 1768 // is required. This avoids extra work of processing the preamble 1769 // headers in parallel multiple times. 1770 Worker->waitForFirstPreamble(); 1771 } 1772 std::shared_ptr<const ASTSignals> Signals; 1773 Preamble = Worker->getPossiblyStalePreamble(&Signals); 1774 1775 std::lock_guard<Semaphore> BarrierLock(Barrier); 1776 WithContext Guard(std::move(Ctx)); 1777 trace::Span Tracer(Name); 1778 SPAN_ATTACH(Tracer, "file", File); 1779 WithContext WithProvidedContext(Opts.ContextProvider(File)); 1780 Action(InputsAndPreamble{Contents, Command, Preamble.get(), Signals.get()}); 1781 }; 1782 1783 PreambleTasks->runAsync("task:" + llvm::sys::path::filename(File), 1784 std::move(Task)); 1785 } 1786 1787 llvm::StringMap<TUScheduler::FileStats> TUScheduler::fileStats() const { 1788 llvm::StringMap<TUScheduler::FileStats> Result; 1789 for (const auto &PathAndFile : Files) 1790 Result.try_emplace(PathAndFile.first(), 1791 PathAndFile.second->Worker->stats()); 1792 return Result; 1793 } 1794 1795 std::vector<Path> TUScheduler::getFilesWithCachedAST() const { 1796 std::vector<Path> Result; 1797 for (auto &&PathAndFile : Files) { 1798 if (!PathAndFile.second->Worker->isASTCached()) 1799 continue; 1800 Result.push_back(std::string(PathAndFile.first())); 1801 } 1802 return Result; 1803 } 1804 1805 DebouncePolicy::clock::duration 1806 DebouncePolicy::compute(llvm::ArrayRef<clock::duration> History) const { 1807 assert(Min <= Max && "Invalid policy"); 1808 if (History.empty()) 1809 return Max; // Arbitrary. 1810 1811 // Base the result on the median rebuild. 1812 // nth_element needs a mutable array, take the chance to bound the data size. 1813 History = History.take_back(15); 1814 llvm::SmallVector<clock::duration, 15> Recent(History.begin(), History.end()); 1815 auto *Median = Recent.begin() + Recent.size() / 2; 1816 std::nth_element(Recent.begin(), Median, Recent.end()); 1817 1818 clock::duration Target = 1819 std::chrono::duration_cast<clock::duration>(RebuildRatio * *Median); 1820 if (Target > Max) 1821 return Max; 1822 if (Target < Min) 1823 return Min; 1824 return Target; 1825 } 1826 1827 DebouncePolicy DebouncePolicy::fixed(clock::duration T) { 1828 DebouncePolicy P; 1829 P.Min = P.Max = T; 1830 return P; 1831 } 1832 1833 void TUScheduler::profile(MemoryTree &MT) const { 1834 for (const auto &Elem : fileStats()) { 1835 MT.detail(Elem.first()) 1836 .child("preamble") 1837 .addUsage(Opts.StorePreamblesInMemory ? Elem.second.UsedBytesPreamble 1838 : 0); 1839 MT.detail(Elem.first()).child("ast").addUsage(Elem.second.UsedBytesAST); 1840 MT.child("header_includer_cache").addUsage(HeaderIncluders->getUsedBytes()); 1841 } 1842 } 1843 } // namespace clangd 1844 } // namespace clang 1845