aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Serialization/ModuleCache.h16
-rw-r--r--clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h15
-rw-r--r--clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h11
-rw-r--r--clang/lib/Serialization/ASTCommon.cpp12
-rw-r--r--clang/lib/Serialization/ASTCommon.h2
-rw-r--r--clang/lib/Serialization/ASTReader.cpp3
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp2
-rw-r--r--clang/lib/Serialization/ModuleCache.cpp23
-rw-r--r--clang/lib/Serialization/ModuleManager.cpp12
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp6
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp6
-rw-r--r--clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp48
12 files changed, 109 insertions, 47 deletions
diff --git a/clang/include/clang/Serialization/ModuleCache.h b/clang/include/clang/Serialization/ModuleCache.h
index a7ba26b..3117d95 100644
--- a/clang/include/clang/Serialization/ModuleCache.h
+++ b/clang/include/clang/Serialization/ModuleCache.h
@@ -12,6 +12,8 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <ctime>
+
namespace llvm {
class AdvisoryLock;
} // namespace llvm
@@ -31,11 +33,23 @@ public:
virtual std::unique_ptr<llvm::AdvisoryLock>
getLock(StringRef ModuleFilename) = 0;
+ // TODO: Abstract away timestamps with isUpToDate() and markUpToDate().
+ // TODO: Consider exposing a "validation lock" API to prevent multiple clients
+ // concurrently noticing an out-of-date module file and validating its inputs.
+
+ /// Returns the timestamp denoting the last time inputs of the module file
+ /// were validated.
+ virtual std::time_t getModuleTimestamp(StringRef ModuleFilename) = 0;
+
+ /// Updates the timestamp denoting the last time inputs of the module file
+ /// were validated.
+ virtual void updateModuleTimestamp(StringRef ModuleFilename) = 0;
+
/// Returns this process's view of the module cache.
virtual InMemoryModuleCache &getInMemoryModuleCache() = 0;
virtual const InMemoryModuleCache &getInMemoryModuleCache() const = 0;
- // TODO: Virtualize writing/reading PCM files, timestamping, pruning, etc.
+ // TODO: Virtualize writing/reading PCM files, pruning, etc.
virtual ~ModuleCache() = default;
};
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
index 5e8b37e..4e97c7b 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
@@ -12,6 +12,7 @@
#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"
#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/Support/Chrono.h"
namespace clang {
namespace tooling {
@@ -84,7 +85,9 @@ public:
DependencyScanningService(
ScanningMode Mode, ScanningOutputFormat Format,
ScanningOptimizations OptimizeArgs = ScanningOptimizations::Default,
- bool EagerLoadModules = false, bool TraceVFS = false);
+ bool EagerLoadModules = false, bool TraceVFS = false,
+ std::time_t BuildSessionTimestamp =
+ llvm::sys::toTimeT(std::chrono::system_clock::now()));
ScanningMode getMode() const { return Mode; }
@@ -100,7 +103,9 @@ public:
return SharedCache;
}
- ModuleCacheMutexes &getModuleCacheMutexes() { return ModCacheMutexes; }
+ ModuleCacheEntries &getModuleCacheEntries() { return ModCacheEntries; }
+
+ std::time_t getBuildSessionTimestamp() const { return BuildSessionTimestamp; }
private:
const ScanningMode Mode;
@@ -113,8 +118,10 @@ private:
const bool TraceVFS;
/// The global file system cache.
DependencyScanningFilesystemSharedCache SharedCache;
- /// The global module cache mutexes.
- ModuleCacheMutexes ModCacheMutexes;
+ /// The global module cache entries.
+ ModuleCacheEntries ModCacheEntries;
+ /// The build session timestamp.
+ std::time_t BuildSessionTimestamp;
};
} // end namespace dependencies
diff --git a/clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h b/clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h
index ba045438..213e60b 100644
--- a/clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h
+++ b/clang/include/clang/Tooling/DependencyScanning/InProcessModuleCache.h
@@ -18,13 +18,18 @@
namespace clang {
namespace tooling {
namespace dependencies {
-struct ModuleCacheMutexes {
+struct ModuleCacheEntry {
+ std::shared_mutex CompilationMutex;
+ std::atomic<std::time_t> Timestamp = 0;
+};
+
+struct ModuleCacheEntries {
std::mutex Mutex;
- llvm::StringMap<std::unique_ptr<std::shared_mutex>> Map;
+ llvm::StringMap<std::unique_ptr<ModuleCacheEntry>> Map;
};
IntrusiveRefCntPtr<ModuleCache>
-makeInProcessModuleCache(ModuleCacheMutexes &Mutexes);
+makeInProcessModuleCache(ModuleCacheEntries &Entries);
} // namespace dependencies
} // namespace tooling
} // namespace clang
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 320ee0e..ad277f1 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -510,15 +510,3 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
return false;
return isa<TagDecl, FieldDecl>(D);
}
-
-void serialization::updateModuleTimestamp(StringRef ModuleFilename) {
- // Overwrite the timestamp file contents so that file's mtime changes.
- std::error_code EC;
- llvm::raw_fd_ostream OS(ModuleFile::getTimestampFilename(ModuleFilename), EC,
- llvm::sys::fs::OF_TextWithCRLF);
- if (EC)
- return;
- OS << "Timestamp file\n";
- OS.close();
- OS.clear_error(); // Avoid triggering a fatal error.
-}
diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h
index ed6b8d0..371db4b 100644
--- a/clang/lib/Serialization/ASTCommon.h
+++ b/clang/lib/Serialization/ASTCommon.h
@@ -100,8 +100,6 @@ inline bool isPartOfPerModuleInitializer(const Decl *D) {
return false;
}
-void updateModuleTimestamp(StringRef ModuleFilename);
-
} // namespace serialization
} // namespace clang
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index e47bac0..a17d622 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4952,7 +4952,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ModuleKind Type,
ImportedModule &M = Loaded[I];
if (M.Mod->Kind == MK_ImplicitModule &&
M.Mod->InputFilesValidationTimestamp < HSOpts.BuildSessionTimestamp)
- updateModuleTimestamp(M.Mod->FileName);
+ getModuleManager().getModuleCache().updateModuleTimestamp(
+ M.Mod->FileName);
}
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 8c5adc3..cccf53d 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5394,7 +5394,7 @@ ASTWriter::WriteAST(llvm::PointerUnion<Sema *, Preprocessor *> Subject,
if (WritingModule && PPRef.getHeaderSearchInfo()
.getHeaderSearchOpts()
.ModulesValidateOncePerBuildSession)
- updateModuleTimestamp(OutputFile);
+ ModCache.updateModuleTimestamp(OutputFile);
if (ShouldCacheASTInMemory) {
// Construct MemoryBuffer and update buffer manager.
diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp
index 955e5f3..4ae49c4 100644
--- a/clang/lib/Serialization/ModuleCache.cpp
+++ b/clang/lib/Serialization/ModuleCache.cpp
@@ -9,6 +9,7 @@
#include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/InMemoryModuleCache.h"
+#include "clang/Serialization/ModuleFile.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/Path.h"
@@ -32,6 +33,28 @@ public:
return std::make_unique<llvm::LockFileManager>(ModuleFilename);
}
+ std::time_t getModuleTimestamp(StringRef ModuleFilename) override {
+ std::string TimestampFilename =
+ serialization::ModuleFile::getTimestampFilename(ModuleFilename);
+ llvm::sys::fs::file_status Status;
+ if (llvm::sys::fs::status(ModuleFilename, Status) != std::error_code{})
+ return 0;
+ return llvm::sys::toTimeT(Status.getLastModificationTime());
+ }
+
+ void updateModuleTimestamp(StringRef ModuleFilename) override {
+ // Overwrite the timestamp file contents so that file's mtime changes.
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(
+ serialization::ModuleFile::getTimestampFilename(ModuleFilename), EC,
+ llvm::sys::fs::OF_TextWithCRLF);
+ if (EC)
+ return;
+ OS << "Timestamp file\n";
+ OS.close();
+ OS.clear_error(); // Avoid triggering a fatal error.
+ }
+
InMemoryModuleCache &getInMemoryModuleCache() override { return InMemory; }
const InMemoryModuleCache &getInMemoryModuleCache() const override {
return InMemory;
diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp
index d466ea0..e3d7ff4 100644
--- a/clang/lib/Serialization/ModuleManager.cpp
+++ b/clang/lib/Serialization/ModuleManager.cpp
@@ -174,15 +174,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
NewModule->ImportLoc = ImportLoc;
NewModule->InputFilesValidationTimestamp = 0;
- if (NewModule->Kind == MK_ImplicitModule) {
- std::string TimestampFilename =
- ModuleFile::getTimestampFilename(NewModule->FileName);
- llvm::vfs::Status Status;
- // A cached stat value would be fine as well.
- if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
- NewModule->InputFilesValidationTimestamp =
- llvm::sys::toTimeT(Status.getLastModificationTime());
- }
+ if (NewModule->Kind == MK_ImplicitModule)
+ NewModule->InputFilesValidationTimestamp =
+ ModCache->getModuleTimestamp(NewModule->FileName);
// Load the contents of the module
if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp
index 96fe40c..7f40c99 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp
@@ -14,6 +14,8 @@ using namespace dependencies;
DependencyScanningService::DependencyScanningService(
ScanningMode Mode, ScanningOutputFormat Format,
- ScanningOptimizations OptimizeArgs, bool EagerLoadModules, bool TraceVFS)
+ ScanningOptimizations OptimizeArgs, bool EagerLoadModules, bool TraceVFS,
+ std::time_t BuildSessionTimestamp)
: Mode(Mode), Format(Format), OptimizeArgs(OptimizeArgs),
- EagerLoadModules(EagerLoadModules), TraceVFS(TraceVFS) {}
+ EagerLoadModules(EagerLoadModules), TraceVFS(TraceVFS),
+ BuildSessionTimestamp(BuildSessionTimestamp) {}
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 2443918..5c9cf3e 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -411,7 +411,7 @@ public:
Scanned = true;
// Create a compiler instance to handle the actual work.
- auto ModCache = makeInProcessModuleCache(Service.getModuleCacheMutexes());
+ auto ModCache = makeInProcessModuleCache(Service.getModuleCacheEntries());
ScanInstanceStorage.emplace(std::move(Invocation),
std::move(PCHContainerOps), ModCache.get());
CompilerInstance &ScanInstance = *ScanInstanceStorage;
@@ -428,6 +428,10 @@ public:
ScanInstance.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath =
true;
+ if (ScanInstance.getHeaderSearchOpts().ModulesValidateOncePerBuildSession)
+ ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp =
+ Service.getBuildSessionTimestamp();
+
ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false;
ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false;
// This will prevent us compiling individual modules asynchronously since
diff --git a/clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp b/clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp
index 71ce4d0..eb05821e 100644
--- a/clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp
+++ b/clang/lib/Tooling/DependencyScanning/InProcessModuleCache.cpp
@@ -10,6 +10,7 @@
#include "clang/Serialization/InMemoryModuleCache.h"
#include "llvm/Support/AdvisoryLock.h"
+#include "llvm/Support/Chrono.h"
#include <mutex>
@@ -50,7 +51,7 @@ public:
};
class InProcessModuleCache : public ModuleCache {
- ModuleCacheMutexes &Mutexes;
+ ModuleCacheEntries &Entries;
// TODO: If we changed the InMemoryModuleCache API and relied on strict
// context hash, we could probably create more efficient thread-safe
@@ -59,19 +60,44 @@ class InProcessModuleCache : public ModuleCache {
InMemoryModuleCache InMemory;
public:
- InProcessModuleCache(ModuleCacheMutexes &Mutexes) : Mutexes(Mutexes) {}
+ InProcessModuleCache(ModuleCacheEntries &Entries) : Entries(Entries) {}
void prepareForGetLock(StringRef Filename) override {}
std::unique_ptr<llvm::AdvisoryLock> getLock(StringRef Filename) override {
- auto &Mtx = [&]() -> std::shared_mutex & {
- std::lock_guard<std::mutex> Lock(Mutexes.Mutex);
- auto &Mutex = Mutexes.Map[Filename];
- if (!Mutex)
- Mutex = std::make_unique<std::shared_mutex>();
- return *Mutex;
+ auto &CompilationMutex = [&]() -> std::shared_mutex & {
+ std::lock_guard Lock(Entries.Mutex);
+ auto &Entry = Entries.Map[Filename];
+ if (!Entry)
+ Entry = std::make_unique<ModuleCacheEntry>();
+ return Entry->CompilationMutex;
}();
- return std::make_unique<ReaderWriterLock>(Mtx);
+ return std::make_unique<ReaderWriterLock>(CompilationMutex);
+ }
+
+ std::time_t getModuleTimestamp(StringRef Filename) override {
+ auto &Timestamp = [&]() -> std::atomic<std::time_t> & {
+ std::lock_guard Lock(Entries.Mutex);
+ auto &Entry = Entries.Map[Filename];
+ if (!Entry)
+ Entry = std::make_unique<ModuleCacheEntry>();
+ return Entry->Timestamp;
+ }();
+
+ return Timestamp.load();
+ }
+
+ void updateModuleTimestamp(StringRef Filename) override {
+ // Note: This essentially replaces FS contention with mutex contention.
+ auto &Timestamp = [&]() -> std::atomic<std::time_t> & {
+ std::lock_guard Lock(Entries.Mutex);
+ auto &Entry = Entries.Map[Filename];
+ if (!Entry)
+ Entry = std::make_unique<ModuleCacheEntry>();
+ return Entry->Timestamp;
+ }();
+
+ Timestamp.store(llvm::sys::toTimeT(std::chrono::system_clock::now()));
}
InMemoryModuleCache &getInMemoryModuleCache() override { return InMemory; }
@@ -82,6 +108,6 @@ public:
} // namespace
IntrusiveRefCntPtr<ModuleCache>
-dependencies::makeInProcessModuleCache(ModuleCacheMutexes &Mutexes) {
- return llvm::makeIntrusiveRefCnt<InProcessModuleCache>(Mutexes);
+dependencies::makeInProcessModuleCache(ModuleCacheEntries &Entries) {
+ return llvm::makeIntrusiveRefCnt<InProcessModuleCache>(Entries);
}