https://github.com/jansvoboda11 updated 
https://github.com/llvm/llvm-project/pull/129751

>From 7dadb10f4e63e419a230270b5f26a145d7015ae7 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Wed, 12 Mar 2025 10:20:16 -0700
Subject: [PATCH] [clang][deps] Implement efficient in-process `ModuleCache`

---
 .../DependencyScanningService.h               |  5 ++
 .../DependencyScanning/InProcessModuleCache.h | 31 +++++++
 .../Tooling/DependencyScanning/CMakeLists.txt |  1 +
 .../DependencyScanningWorker.cpp              |  5 +-
 .../InProcessModuleCache.cpp                  | 87 +++++++++++++++++++
 5 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 
clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h
 create mode 100644 
clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp

diff --git 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
index 816e122eb3003..996a26716eea2 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGSERVICE_H
 
 #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"
+#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
 #include "llvm/ADT/BitmaskEnum.h"
 
 namespace clang {
@@ -99,6 +100,8 @@ class DependencyScanningService {
     return SharedCache;
   }
 
+  ModuleCacheMutexes &getModuleCacheMutexes() { return ModuleCacheMutexes; }
+
 private:
   const ScanningMode Mode;
   const ScanningOutputFormat Format;
@@ -110,6 +113,8 @@ class DependencyScanningService {
   const bool TraceVFS;
   /// The global file system cache.
   DependencyScanningFilesystemSharedCache SharedCache;
+  /// The global module cache mutexes.
+  ModuleCacheMutexes ModuleCacheMutexes;
 };
 
 } // end namespace dependencies
diff --git 
a/clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h 
b/clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h
new file mode 100644
index 0000000000000..a22647584d8c5
--- /dev/null
+++ b/clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_INPROCESSMODULECACHE_H
+#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_INPROCESSMODULECACHE_H
+
+#include "clang/Serialization/ModuleCache.h"
+#include "llvm/ADT/StringMap.h"
+
+#include <shared_mutex>
+
+namespace clang {
+namespace tooling {
+namespace dependencies {
+struct ModuleCacheMutexes {
+  std::mutex Mutex;
+  llvm::StringMap<std::unique_ptr<std::shared_mutex>> Map;
+};
+
+IntrusiveRefCntPtr<ModuleCache>
+makeInProcessModuleCache(ModuleCacheMutexes &Mutexes);
+} // namespace dependencies
+} // namespace tooling
+} // namespace clang
+
+#endif
diff --git a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt 
b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
index 6b500a183bcfc..993dc093a781c 100644
--- a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
+++ b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_library(clangDependencyScanning
   DependencyScanningService.cpp
   DependencyScanningWorker.cpp
   DependencyScanningTool.cpp
+  InProcessModuleCache.cpp
   ModuleDepCollector.cpp
 
   DEPENDS
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 697f26ee5d12f..ca15a088c308d 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -22,6 +22,7 @@
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Serialization/ObjectFilePCHContainerReader.h"
 #include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
+#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
 #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -315,9 +316,11 @@ class DependencyScanningAction : public 
tooling::ToolAction {
     Scanned = true;
 
     // Create a compiler instance to handle the actual work.
-    ScanInstanceStorage.emplace(std::move(PCHContainerOps));
+    auto ModCache = makeInProcessModuleCache(Service.getModuleCacheMutexes());
+    ScanInstanceStorage.emplace(std::move(PCHContainerOps), ModCache.get());
     CompilerInstance &ScanInstance = *ScanInstanceStorage;
     ScanInstance.setInvocation(std::move(Invocation));
+    ScanInstance.setBuildingModule(false);
 
     // Create the compiler's actual diagnostics engine.
     sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
diff --git a/clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp 
b/clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp
new file mode 100644
index 0000000000000..079e00c38b140
--- /dev/null
+++ b/clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
+
+#include "clang/Serialization/InMemoryModuleCache.h"
+#include "llvm/Support/AdvisoryLock.h"
+
+#include <mutex>
+
+using namespace clang;
+using namespace tooling;
+using namespace dependencies;
+
+namespace {
+class ReaderWriterLock : public llvm::AdvisoryLock {
+  // TODO: Consider using std::atomic::{wait,notify_all} when we move to C++20.
+  std::unique_lock<std::shared_mutex> OwningLock;
+
+public:
+  ReaderWriterLock(std::shared_mutex &Mutex)
+      : OwningLock(Mutex, std::defer_lock) {}
+
+  Expected<bool> tryLock() override { return OwningLock.try_lock(); }
+
+  llvm::WaitForUnlockResult
+  waitForUnlockFor(std::chrono::seconds MaxSeconds) override {
+    assert(!OwningLock);
+    // We do not respect the timeout here. It's very generous for implicit
+    // modules, so we'd typically only reach it if the owner crashed (but so 
did
+    // we, since we run in the same process), or encountered deadlock.
+    (void)MaxSeconds;
+    std::shared_lock Lock(*OwningLock.mutex());
+    return llvm::WaitForUnlockResult::Success;
+  }
+
+  std::error_code unsafeMaybeUnlock() override {
+    // Unlocking the mutex here would trigger UB and we don't expect this to be
+    // actually called when compiling scanning modules due to the no-timeout
+    // guarantee above.
+    return {};
+  }
+
+  ~ReaderWriterLock() override = default;
+};
+
+class InProcessModuleCache : public ModuleCache {
+  ModuleCacheMutexes &Mutexes;
+
+  // TODO: If we changed the InMemoryModuleCache API and relied on strict
+  // context hash, we could probably create more efficient thread-safe
+  // implementation of the InMemoryModuleCache such that it does need to be
+  // recreated for each translation unit.
+  InMemoryModuleCache InMemory;
+
+public:
+  InProcessModuleCache(ModuleCacheMutexes &Mutexes) : Mutexes(Mutexes) {}
+
+  void prepareForGetLock(StringRef Filename) override {}
+
+  std::unique_ptr<llvm::AdvisoryLock> getLock(StringRef Filename) override {
+    auto &Mtx = [&]() -> std::shared_mutex & {
+      std::lock_guard Lock(Mutexes.Mutex);
+      auto &Mutex = Mutexes.Map[Filename];
+      if (!Mutex)
+        Mutex = std::make_unique<std::shared_mutex>();
+      return *Mutex;
+    }();
+    return std::make_unique<ReaderWriterLock>(Mtx);
+  }
+
+  InMemoryModuleCache &getInMemoryModuleCache() override { return InMemory; }
+  const InMemoryModuleCache &getInMemoryModuleCache() const override {
+    return InMemory;
+  }
+};
+} // namespace
+
+IntrusiveRefCntPtr<ModuleCache>
+dependencies::makeInProcessModuleCache(ModuleCacheMutexes &Mutexes) {
+  return llvm::makeIntrusiveRefCnt<InProcessModuleCache>(Mutexes);
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to