Skip to content

Commit eebebd9

Browse files
committed
[Dependency Scanning] Do not persist cached Clang module dependencies between scans.
This change tweaks the 'GlobalModuleDependenciesCache', which persists across scanner invocations with the same 'DependencyScanningTool' to no longer cache discovered Clang modules. Doing so felt like a premature optimization, and we should instead attempt to share as much state as possible by keeping around the actual Clang scanner's state, which performs its own caching. Caching discovered dependencies both in the Clang scanner instance, and in our own cache is much more error-prone - the Clang scanner has a richer context for what is okay and not okay to cache/re-use. Instead, we still cache discovered Clang dependencies *within* a given scan, since those are discovered using a common Clang scanner instance and should be safe to keep for the duration of the scan. This change should make it simpler to pin down the core functionality and correctness of the scanner. Once we turn our attention to the scanner's performance, we can revisit this strategy and optimize the caching behaviour.
1 parent cd04e9e commit eebebd9

File tree

10 files changed

+69
-45
lines changed

10 files changed

+69
-45
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,6 @@ class GlobalModuleDependenciesCache {
527527
GlobalModuleDependenciesCache(const GlobalModuleDependenciesCache &) = delete;
528528
GlobalModuleDependenciesCache &
529529
operator=(const GlobalModuleDependenciesCache &) = delete;
530-
531530
virtual ~GlobalModuleDependenciesCache() {}
532531

533532
void configureForTriple(std::string triple);
@@ -603,24 +602,18 @@ class ModuleDependenciesCache {
603602
private:
604603
GlobalModuleDependenciesCache &globalCache;
605604

606-
/// References to data in `globalCache` for dependencies accimulated during
605+
/// References to data in `globalCache` for Swift dependencies and
606+
/// `clangModuleDependencies` for Clang dependencies accimulated during
607607
/// the current scanning action.
608608
ModuleDependenciesKindRefMap ModuleDependenciesMap;
609609

610-
/// Additional information needed for Clang dependency scanning.
611-
ClangModuleDependenciesCacheImpl *clangImpl = nullptr;
612-
613-
/// Name of the main Swift module of this scan
614-
StringRef mainModuleName;
615-
/// Underlying Clang module is seen differently by the main
616-
/// module and by module clients. For this reason, we do not wish subsequent
617-
/// scans to be able to re-use this dependency info and therefore we avoid
618-
/// adding it to the global cache. The dependency storage is therefore tied
619-
/// to this, local, cache.
620-
std::unique_ptr<ModuleDependencies> underlyingClangModuleDependency = nullptr;
610+
/// Discovered Clang modules are only cached locally.
611+
llvm::StringMap<ModuleDependenciesVector> clangModuleDependencies;
621612

622613
/// Function that will delete \c clangImpl properly.
623614
void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *) = nullptr;
615+
/// Additional information needed for Clang dependency scanning.
616+
ClangModuleDependenciesCacheImpl *clangImpl = nullptr;
624617

625618
/// Free up the storage associated with the Clang implementation.
626619
void destroyClangImpl() {
@@ -647,8 +640,7 @@ class ModuleDependenciesCache {
647640
Optional<ModuleDependenciesKind> kind) const;
648641

649642
public:
650-
ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache,
651-
StringRef mainModuleName);
643+
ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache);
652644
ModuleDependenciesCache(const ModuleDependenciesCache &) = delete;
653645
ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete;
654646
virtual ~ModuleDependenciesCache() { destroyClangImpl(); }

include/swift/AST/ModuleLoader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919

2020
#include "swift/AST/Identifier.h"
2121
#include "swift/AST/Import.h"
22-
#include "swift/AST/ModuleDependencies.h"
2322
#include "swift/Basic/ArrayRefView.h"
2423
#include "swift/Basic/Fingerprint.h"
2524
#include "swift/Basic/LLVM.h"
2625
#include "swift/Basic/Located.h"
2726
#include "swift/Basic/SourceLoc.h"
2827
#include "llvm/ADT/SetVector.h"
28+
#include "llvm/ADT/StringSet.h"
2929
#include "llvm/ADT/TinyPtrVector.h"
3030
#include "llvm/Support/VersionTuple.h"
3131
#include <system_error>
@@ -52,6 +52,7 @@ class NominalTypeDecl;
5252
class SourceFile;
5353
class TypeDecl;
5454
class CompilerInstance;
55+
enum class ModuleDependenciesKind : int8_t;
5556

5657
enum class KnownProtocolKind : uint8_t;
5758

include/swift/Sema/SourceLoader.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#ifndef SWIFT_SEMA_SOURCELOADER_H
1414
#define SWIFT_SEMA_SOURCELOADER_H
1515

16-
#include "swift/AST/ModuleDependencies.h"
1716
#include "swift/AST/ModuleLoader.h"
1817

1918
namespace swift {
@@ -94,14 +93,10 @@ class SourceLoader : public ModuleLoader {
9493
// Parsing populates the Objective-C method tables.
9594
}
9695

97-
Optional<ModuleDependencies> getModuleDependencies(
98-
StringRef moduleName, ModuleDependenciesCache &cache,
99-
InterfaceSubContextDelegate &delegate) override {
100-
// FIXME: Implement?
101-
return None;
102-
}
96+
Optional<ModuleDependencies>
97+
getModuleDependencies(StringRef moduleName, ModuleDependenciesCache &cache,
98+
InterfaceSubContextDelegate &delegate) override;
10399
};
104-
105100
}
106101

107102
#endif

lib/AST/ModuleDependencies.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ GlobalModuleDependenciesCache::findSourceModuleDependency(
388388

389389
bool GlobalModuleDependenciesCache::hasDependencies(
390390
StringRef moduleName, ModuleLookupSpecifics details) const {
391+
assert(details.kind != ModuleDependenciesKind::Clang &&
392+
"Attempting to query Clang dependency in persistent Dependency "
393+
"Scanner Cache.");
391394
return findDependencies(moduleName, details).hasValue();
392395
}
393396

@@ -397,6 +400,9 @@ GlobalModuleDependenciesCache::findAllDependenciesIrrespectiveOfSearchPaths(
397400
if (!kind) {
398401
for (auto kind = ModuleDependenciesKind::FirstKind;
399402
kind != ModuleDependenciesKind::LastKind; ++kind) {
403+
if (kind == ModuleDependenciesKind::Clang)
404+
continue;
405+
400406
auto deps =
401407
findAllDependenciesIrrespectiveOfSearchPaths(moduleName, kind);
402408
if (deps.hasValue())
@@ -446,6 +452,10 @@ static std::string modulePathForVerification(const ModuleDependencies &module) {
446452
const ModuleDependencies *GlobalModuleDependenciesCache::recordDependencies(
447453
StringRef moduleName, ModuleDependencies dependencies) {
448454
auto kind = dependencies.getKind();
455+
assert(kind != ModuleDependenciesKind::Clang &&
456+
"Attempting to cache Clang dependency in persistent Dependency "
457+
"Scanner Cache.");
458+
449459
// Source-based dependencies are recorded independently of the invocation's
450460
// target triple.
451461
if (kind == swift::ModuleDependenciesKind::SwiftSource) {
@@ -482,6 +492,10 @@ const ModuleDependencies *GlobalModuleDependenciesCache::recordDependencies(
482492
const ModuleDependencies *GlobalModuleDependenciesCache::updateDependencies(
483493
ModuleDependencyID moduleID, ModuleDependencies dependencies) {
484494
auto kind = dependencies.getKind();
495+
assert(kind != ModuleDependenciesKind::Clang &&
496+
"Attempting to update Clang dependency in persistent Dependency "
497+
"Scanner Cache.");
498+
485499
// Source-based dependencies
486500
if (kind == swift::ModuleDependenciesKind::SwiftSource) {
487501
assert(SwiftSourceModuleDependenciesMap.count(moduleID.first) == 1 &&
@@ -517,9 +531,8 @@ ModuleDependenciesCache::getDependencyReferencesMap(
517531
}
518532

519533
ModuleDependenciesCache::ModuleDependenciesCache(
520-
GlobalModuleDependenciesCache &globalCache,
521-
StringRef mainModuleName)
522-
: globalCache(globalCache), mainModuleName(mainModuleName) {
534+
GlobalModuleDependenciesCache &globalCache)
535+
: globalCache(globalCache) {
523536
for (auto kind = ModuleDependenciesKind::FirstKind;
524537
kind != ModuleDependenciesKind::LastKind; ++kind) {
525538
ModuleDependenciesMap.insert(
@@ -572,12 +585,29 @@ void ModuleDependenciesCache::recordDependencies(
572585
// The underlying Clang module needs to be cached in this invocation,
573586
// but should not make it to the global cache since it will look slightly
574587
// differently for clients of this module than it does for the module itself.
575-
const ModuleDependencies* recordedDependencies;
576-
if (moduleName == mainModuleName && dependencies.isClangModule()) {
577-
underlyingClangModuleDependency = std::make_unique<ModuleDependencies>(std::move(dependencies));
578-
recordedDependencies = underlyingClangModuleDependency.get();
588+
const ModuleDependencies *recordedDependencies;
589+
if (dependencies.getKind() == ModuleDependenciesKind::Clang) {
590+
auto *clangDep = dependencies.getAsClangModule();
591+
assert(clangDep && "Unexpected NULL Clang dependency.");
592+
// Cache may already have a dependency for this module
593+
if (clangModuleDependencies.count(moduleName) != 0) {
594+
// Do not record duplicate dependencies.
595+
auto newModulePath = clangDep->moduleMapFile;
596+
for (auto &existingDeps : clangModuleDependencies[moduleName]) {
597+
if (modulePathForVerification(existingDeps) == newModulePath)
598+
return;
599+
}
600+
clangModuleDependencies[moduleName].emplace_back(std::move(dependencies));
601+
recordedDependencies = clangModuleDependencies[moduleName].end() - 1;
602+
} else {
603+
clangModuleDependencies.insert(
604+
{moduleName, ModuleDependenciesVector{std::move(dependencies)}});
605+
recordedDependencies = &(clangModuleDependencies[moduleName].front());
606+
}
607+
579608
} else
580-
recordedDependencies = globalCache.recordDependencies(moduleName, dependencies);
609+
recordedDependencies =
610+
globalCache.recordDependencies(moduleName, dependencies);
581611

582612
auto &map = getDependencyReferencesMap(dependenciesKind);
583613
assert(map.count(moduleName) == 0 && "Already added to map");

lib/AST/ModuleLoader.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/DiagnosticsCommon.h"
1919
#include "swift/AST/FileUnit.h"
2020
#include "swift/AST/ModuleLoader.h"
21+
#include "swift/AST/ModuleDependencies.h"
2122
#include "swift/Basic/FileTypes.h"
2223
#include "swift/Basic/Platform.h"
2324
#include "swift/Basic/SourceManager.h"

lib/ClangImporter/ImporterImpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <functional>
5454
#include <set>
5555
#include <unordered_set>
56+
#include <unordered_map>
5657
#include <vector>
5758

5859
namespace llvm {

lib/DependencyScan/DependencyScanningTool.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ DependencyScanningTool::getDependencies(
7373
auto Instance = std::move(*InstanceOrErr);
7474

7575
// Local scan cache instance, wrapping the shared global cache.
76-
ModuleDependenciesCache cache(*SharedCache,
77-
Instance->getMainModule()->getNameStr());
76+
ModuleDependenciesCache cache(*SharedCache);
7877
// Execute the scanning action, retrieving the in-memory result
7978
auto DependenciesOrErr = performModuleScan(*Instance.get(), cache);
8079
if (DependenciesOrErr.getError())
@@ -114,8 +113,7 @@ DependencyScanningTool::getDependencies(
114113
auto Instance = std::move(*InstanceOrErr);
115114

116115
// Local scan cache instance, wrapping the shared global cache.
117-
ModuleDependenciesCache cache(*SharedCache,
118-
Instance->getMainModule()->getNameStr());
116+
ModuleDependenciesCache cache(*SharedCache);
119117
auto BatchScanResults = performBatchModuleScan(
120118
*Instance.get(), cache, VersionedPCMInstanceCacheCache.get(),
121119
Saver, BatchInput);

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ forEachBatchEntry(CompilerInstance &invocationInstance,
11091109
newGlobalCache->configureForTriple(
11101110
newInstance->getInvocation().getLangOptions().Target.str());
11111111
auto newLocalCache = std::make_unique<ModuleDependenciesCache>(
1112-
*newGlobalCache, newInstance->getMainModule()->getNameStr());
1112+
*newGlobalCache);
11131113
pInstance = newInstance.get();
11141114
pCache = newLocalCache.get();
11151115
subInstanceMap->insert(
@@ -1253,8 +1253,7 @@ bool swift::dependencies::scanDependencies(CompilerInstance &instance) {
12531253
if (opts.ReuseDependencyScannerCache)
12541254
deserializeDependencyCache(instance, globalCache);
12551255

1256-
ModuleDependenciesCache cache(globalCache,
1257-
instance.getMainModule()->getNameStr());
1256+
ModuleDependenciesCache cache(globalCache);
12581257

12591258
// Execute scan
12601259
auto dependenciesOrErr = performModuleScan(instance, cache);
@@ -1289,8 +1288,7 @@ bool swift::dependencies::prescanDependencies(CompilerInstance &instance) {
12891288
GlobalModuleDependenciesCache singleUseGlobalCache;
12901289
singleUseGlobalCache.configureForTriple(instance.getInvocation()
12911290
.getLangOptions().Target.str());
1292-
ModuleDependenciesCache cache(singleUseGlobalCache,
1293-
instance.getMainModule()->getNameStr());
1291+
ModuleDependenciesCache cache(singleUseGlobalCache);
12941292
if (out.has_error() || EC) {
12951293
Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path,
12961294
EC.message());
@@ -1321,8 +1319,7 @@ bool swift::dependencies::batchScanDependencies(
13211319
GlobalModuleDependenciesCache singleUseGlobalCache;
13221320
singleUseGlobalCache.configureForTriple(instance.getInvocation()
13231321
.getLangOptions().Target.str());
1324-
ModuleDependenciesCache cache(singleUseGlobalCache,
1325-
instance.getMainModule()->getNameStr());
1322+
ModuleDependenciesCache cache(singleUseGlobalCache);
13261323
(void)instance.getMainModule();
13271324
llvm::BumpPtrAllocator alloc;
13281325
llvm::StringSaver saver(alloc);
@@ -1357,8 +1354,7 @@ bool swift::dependencies::batchPrescanDependencies(
13571354
GlobalModuleDependenciesCache singleUseGlobalCache;
13581355
singleUseGlobalCache.configureForTriple(instance.getInvocation()
13591356
.getLangOptions().Target.str());
1360-
ModuleDependenciesCache cache(singleUseGlobalCache,
1361-
instance.getMainModule()->getNameStr());
1357+
ModuleDependenciesCache cache(singleUseGlobalCache);
13621358
(void)instance.getMainModule();
13631359
llvm::BumpPtrAllocator alloc;
13641360
llvm::StringSaver saver(alloc);

lib/Frontend/Frontend.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/DiagnosticsSema.h"
2222
#include "swift/AST/FileSystem.h"
2323
#include "swift/AST/Module.h"
24+
#include "swift/AST/ModuleDependencies.h"
2425
#include "swift/AST/TypeCheckRequests.h"
2526
#include "swift/Basic/FileTypes.h"
2627
#include "swift/Basic/SourceManager.h"

lib/Sema/SourceLoader.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTContext.h"
2121
#include "swift/AST/DiagnosticsSema.h"
2222
#include "swift/AST/Module.h"
23+
#include "swift/AST/ModuleDependencies.h"
2324
#include "swift/AST/SourceFile.h"
2425
#include "swift/Parse/PersistentParserState.h"
2526
#include "swift/Basic/SourceManager.h"
@@ -149,3 +150,11 @@ void SourceLoader::loadExtensions(NominalTypeDecl *nominal,
149150
// Type-checking the source automatically loads all extensions; there's
150151
// nothing to do here.
151152
}
153+
154+
Optional<ModuleDependencies>
155+
SourceLoader::getModuleDependencies(StringRef moduleName,
156+
ModuleDependenciesCache &cache,
157+
InterfaceSubContextDelegate &delegate) {
158+
// FIXME: Implement?
159+
return None;
160+
}

0 commit comments

Comments
 (0)