Skip to content

Commit 717002d

Browse files
committed
[Dependency Scanning] Copy the set of already-seen clang modules before parallel Clang identifier query
This set, belonging to 'ModuleDependenciesCache', is only updated in a critical section behind a lock in the scanner. However, it is queried unsynchronized inside the Clang scanner itself. If an update causes a re-hash to happen, chaose can ensue with concurrent lookups. Since this set only affects the produced set of results from teh Clang scanning query, we should simply pass in an immutable copy to scanning queries and rely on downstream de-duplication of scanning results. With this, we can avoid passing in the reference to `ModuleDependenciesCache` to the 'scanFilesystemFor*ModuleDependency' altogether. Resolves rdar://139414443
1 parent 8feb497 commit 717002d

File tree

2 files changed

+39
-50
lines changed

2 files changed

+39
-50
lines changed

include/swift/DependencyScan/ModuleDependencyScanner.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,17 @@ class ModuleDependencyScanningWorker {
3535
DependencyTracker &DependencyTracker, DiagnosticEngine &diags);
3636

3737
private:
38-
/// Retrieve the module dependencies for the module with the given name.
39-
ModuleDependencyVector
40-
scanFilesystemForModuleDependency(Identifier moduleName,
41-
const ModuleDependenciesCache &cache,
42-
bool isTestableImport = false);
43-
4438
/// Retrieve the module dependencies for the Clang module with the given name.
4539
ModuleDependencyVector
4640
scanFilesystemForClangModuleDependency(Identifier moduleName,
47-
const ModuleDependenciesCache &cache);
41+
StringRef moduleOutputPath,
42+
const llvm::DenseSet<clang::tooling::dependencies::ModuleID> &alreadySeenModules,
43+
llvm::PrefixMapper *prefixMapper);
4844

4945
/// Retrieve the module dependencies for the Swift module with the given name.
5046
ModuleDependencyVector
51-
scanFilesystemForSwiftModuleDependency(Identifier moduleName,
52-
const ModuleDependenciesCache &cache,
47+
scanFilesystemForSwiftModuleDependency(Identifier moduleName, StringRef moduleOutputPath,
48+
llvm::PrefixMapper *prefixMapper,
5349
bool isTestableImport = false);
5450

5551
// Worker-specific instance of CompilerInvocation

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -223,45 +223,26 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker(
223223
workerCompilerInvocation->getSearchPathOptions().ModuleLoadMode);
224224
}
225225

226-
ModuleDependencyVector
227-
ModuleDependencyScanningWorker::scanFilesystemForModuleDependency(
228-
Identifier moduleName, const ModuleDependenciesCache &cache,
229-
bool isTestableImport) {
230-
// First query a Swift module, otherwise lookup a Clang module
231-
ModuleDependencyVector moduleDependencies =
232-
swiftScannerModuleLoader->getModuleDependencies(
233-
moduleName, cache.getModuleOutputPath(),
234-
cache.getAlreadySeenClangModules(), clangScanningTool,
235-
*scanningASTDelegate, cache.getScanService().getPrefixMapper(),
236-
isTestableImport);
237-
238-
if (moduleDependencies.empty())
239-
moduleDependencies = clangScannerModuleLoader->getModuleDependencies(
240-
moduleName, cache.getModuleOutputPath(),
241-
cache.getAlreadySeenClangModules(), clangScanningTool,
242-
*scanningASTDelegate, cache.getScanService().getPrefixMapper(),
243-
isTestableImport);
244-
245-
return moduleDependencies;
246-
}
247-
248226
ModuleDependencyVector
249227
ModuleDependencyScanningWorker::scanFilesystemForSwiftModuleDependency(
250-
Identifier moduleName, const ModuleDependenciesCache &cache,
251-
bool isTestableImport) {
228+
Identifier moduleName, StringRef moduleOutputPath,
229+
llvm::PrefixMapper *prefixMapper, bool isTestableImport) {
252230
return swiftScannerModuleLoader->getModuleDependencies(
253-
moduleName, cache.getModuleOutputPath(),
254-
cache.getAlreadySeenClangModules(), clangScanningTool,
255-
*scanningASTDelegate, cache.getScanService().getPrefixMapper(), isTestableImport);
231+
moduleName, moduleOutputPath,
232+
{}, clangScanningTool, *scanningASTDelegate,
233+
prefixMapper, isTestableImport);
256234
}
257235

258236
ModuleDependencyVector
259237
ModuleDependencyScanningWorker::scanFilesystemForClangModuleDependency(
260-
Identifier moduleName, const ModuleDependenciesCache &cache) {
238+
Identifier moduleName,
239+
StringRef moduleOutputPath,
240+
const llvm::DenseSet<clang::tooling::dependencies::ModuleID> &alreadySeenModules,
241+
llvm::PrefixMapper *prefixMapper) {
261242
return clangScannerModuleLoader->getModuleDependencies(
262-
moduleName, cache.getModuleOutputPath(),
263-
cache.getAlreadySeenClangModules(), clangScanningTool,
264-
*scanningASTDelegate, cache.getScanService().getPrefixMapper(), false);
243+
moduleName, moduleOutputPath,
244+
alreadySeenModules, clangScanningTool,
245+
*scanningASTDelegate, prefixMapper, false);
265246
}
266247

267248
template <typename Function, typename... Args>
@@ -503,7 +484,9 @@ ModuleDependencyScanner::getNamedClangModuleDependencyInfo(
503484
auto moduleDependencies = withDependencyScanningWorker(
504485
[&cache, moduleIdentifier](ModuleDependencyScanningWorker *ScanningWorker) {
505486
return ScanningWorker->scanFilesystemForClangModuleDependency(
506-
moduleIdentifier, cache);
487+
moduleIdentifier, cache.getModuleOutputPath(),
488+
cache.getAlreadySeenClangModules(),
489+
cache.getScanService().getPrefixMapper());
507490
});
508491
if (moduleDependencies.empty())
509492
return std::nullopt;
@@ -539,7 +522,8 @@ ModuleDependencyScanner::getNamedSwiftModuleDependencyInfo(
539522
auto moduleDependencies = withDependencyScanningWorker(
540523
[&cache, moduleIdentifier](ModuleDependencyScanningWorker *ScanningWorker) {
541524
return ScanningWorker->scanFilesystemForSwiftModuleDependency(
542-
moduleIdentifier, cache);
525+
moduleIdentifier, cache.getModuleOutputPath(),
526+
cache.getScanService().getPrefixMapper());
543527
});
544528
if (moduleDependencies.empty())
545529
return std::nullopt;
@@ -755,29 +739,36 @@ ModuleDependencyScanner::resolveAllClangModuleDependencies(
755739
moduleLookupResult.insert(
756740
std::make_pair(unresolvedIdentifier.getKey(), std::nullopt));
757741

758-
std::mutex CacheAccessLock;
742+
// We need a copy of the shared already-seen module set, which will be shared amongst
743+
// all the workers. In `recordDependencies`, each worker will contribute its
744+
// results back to the shared set for future lookups.
745+
const llvm::DenseSet<clang::tooling::dependencies::ModuleID> seenClangModules =
746+
cache.getAlreadySeenClangModules();
747+
std::mutex cacheAccessLock;
759748
auto scanForClangModuleDependency =
760-
[this, &cache, &moduleLookupResult, &CacheAccessLock](Identifier moduleIdentifier) {
749+
[this, &cache, &moduleLookupResult,
750+
&cacheAccessLock, &seenClangModules](Identifier moduleIdentifier) {
761751
auto moduleName = moduleIdentifier.str();
762752
{
763-
std::lock_guard<std::mutex> guard(CacheAccessLock);
753+
std::lock_guard<std::mutex> guard(cacheAccessLock);
764754
if (cache.hasDependency(moduleName, ModuleDependencyKind::Clang))
765755
return;
766756
}
767757

768758
auto moduleDependencies = withDependencyScanningWorker(
769-
[&cache,
759+
[&cache, &seenClangModules,
770760
moduleIdentifier](ModuleDependencyScanningWorker *ScanningWorker) {
771761
return ScanningWorker->scanFilesystemForClangModuleDependency(
772-
moduleIdentifier, cache);
762+
moduleIdentifier, cache.getModuleOutputPath(),
763+
seenClangModules, cache.getScanService().getPrefixMapper());
773764
});
774765

775766
// Update the `moduleLookupResult` and cache all discovered dependencies
776767
// so that subsequent queries do not have to call into the scanner
777768
// if looking for a module that was discovered as a transitive dependency
778769
// in this scan.
779770
{
780-
std::lock_guard<std::mutex> guard(CacheAccessLock);
771+
std::lock_guard<std::mutex> guard(cacheAccessLock);
781772
moduleLookupResult.insert_or_assign(moduleName, moduleDependencies);
782773
if (!moduleDependencies.empty())
783774
cache.recordDependencies(moduleDependencies);
@@ -952,7 +943,8 @@ void ModuleDependencyScanner::resolveSwiftImportsForModule(
952943
[&cache, moduleIdentifier,
953944
isTestable](ModuleDependencyScanningWorker *ScanningWorker) {
954945
return ScanningWorker->scanFilesystemForSwiftModuleDependency(
955-
moduleIdentifier, cache, isTestable);
946+
moduleIdentifier, cache.getModuleOutputPath(),
947+
cache.getScanService().getPrefixMapper(), isTestable);
956948
});
957949
moduleLookupResult.insert_or_assign(moduleName, moduleDependencies);
958950
};
@@ -1094,7 +1086,8 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
10941086
[&cache,
10951087
moduleIdentifier](ModuleDependencyScanningWorker *ScanningWorker) {
10961088
return ScanningWorker->scanFilesystemForSwiftModuleDependency(
1097-
moduleIdentifier, cache);
1089+
moduleIdentifier, cache.getModuleOutputPath(),
1090+
cache.getScanService().getPrefixMapper());
10981091
});
10991092
swiftOverlayLookupResult.insert_or_assign(moduleName, moduleDependencies);
11001093
};

0 commit comments

Comments
 (0)