Skip to content

Commit 1b1d91d

Browse files
committed
[Dependency Scanning] Reduce the amount of copying of collections of module IDs
Previously, frequently-used methods like 'getAllDependencies' and 'getAllClangDependencies' had to aggregate (copy) multiple collections stored in a 'ModuleDependencyInfo' into a new result array to present to the client. These methods have been refactored to instead return an iterable joined view of the constituent collections.
1 parent b0c1160 commit 1b1d91d

File tree

4 files changed

+120
-67
lines changed

4 files changed

+120
-67
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,69 @@ struct ModuleDependencyIDHash {
9494
}
9595
};
9696

97+
// An iterable view over multiple joined ArrayRefs
98+
// FIXME: std::ranges::join_view
99+
template <typename T>
100+
class JoinedArrayRefView {
101+
public:
102+
class Iterator {
103+
public:
104+
using iterator_category = std::forward_iterator_tag;
105+
using value_type = T;
106+
using difference_type = std::ptrdiff_t;
107+
using pointer = const T*;
108+
using reference = const T&;
109+
Iterator(const JoinedArrayRefView *parent, size_t memberIndex,
110+
size_t elementIndex)
111+
: parentView(parent), collectionIndex(memberIndex),
112+
elementIndex(elementIndex) {
113+
checkAdvance();
114+
}
115+
const T &operator*() const {
116+
return (parentView->memberCollections[collectionIndex])[elementIndex];
117+
}
118+
const T *operator->() const {
119+
return &(parentView->memberCollections[collectionIndex])[elementIndex];
120+
}
121+
Iterator &operator++() {
122+
++elementIndex;
123+
checkAdvance();
124+
return *this;
125+
}
126+
bool operator==(const Iterator &other) const {
127+
return collectionIndex == other.collectionIndex &&
128+
elementIndex == other.elementIndex;
129+
}
130+
bool operator!=(const Iterator &other) const { return !(*this == other); }
131+
132+
private:
133+
const JoinedArrayRefView *parentView;
134+
size_t collectionIndex;
135+
size_t elementIndex;
136+
137+
void checkAdvance() {
138+
while (collectionIndex < parentView->memberCollections.size() &&
139+
elementIndex >= parentView->memberCollections[collectionIndex].size()) {
140+
++collectionIndex;
141+
elementIndex = 0;
142+
}
143+
}
144+
};
145+
146+
Iterator begin() const { return Iterator(this, 0, 0); }
147+
Iterator end() const { return Iterator(this, memberCollections.size(), 0); }
148+
149+
template <typename... Arrays>
150+
JoinedArrayRefView(Arrays ...arrs) {
151+
memberCollections.reserve(sizeof...(arrs));
152+
(memberCollections.push_back(arrs), ...);
153+
}
154+
155+
private:
156+
std::vector<ArrayRef<T>> memberCollections;
157+
};
158+
using ModuleDependencyIDCollectionView = JoinedArrayRefView<ModuleDependencyID>;
159+
97160
using ModuleDependencyIDSet =
98161
std::unordered_set<ModuleDependencyID, ModuleDependencyIDHash>;
99162
using ModuleDependencyIDSetVector =
@@ -719,8 +782,8 @@ class ModuleDependencyInfo {
719782
return storage->swiftOverlayDependencies;
720783
}
721784

722-
void
723-
setCrossImportOverlayDependencies(const ArrayRef<ModuleDependencyID> dependencyIDs) {
785+
void setCrossImportOverlayDependencies(
786+
const ModuleDependencyIDCollectionView dependencyIDs) {
724787
assert(isSwiftModule());
725788
storage->crossImportOverlayModules.assign(dependencyIDs.begin(),
726789
dependencyIDs.end());
@@ -1051,12 +1114,16 @@ class ModuleDependenciesCache {
10511114
}
10521115

10531116
/// Query all dependencies
1054-
ModuleDependencyIDSetVector
1117+
ModuleDependencyIDCollectionView
10551118
getAllDependencies(const ModuleDependencyID &moduleID) const;
10561119

1120+
/// Query all directly-imported dependencies
1121+
ModuleDependencyIDCollectionView
1122+
getDirectImportedDependencies(const ModuleDependencyID &moduleID) const;
1123+
10571124
/// Query all Clang module dependencies.
1058-
ModuleDependencyIDSetVector
1059-
getClangDependencies(const ModuleDependencyID &moduleID) const;
1125+
ModuleDependencyIDCollectionView
1126+
getAllClangDependencies(const ModuleDependencyID &moduleID) const;
10601127

10611128
/// Query all directly-imported Swift dependencies
10621129
llvm::ArrayRef<ModuleDependencyID>
@@ -1138,9 +1205,9 @@ class ModuleDependenciesCache {
11381205
setHeaderClangDependencies(ModuleDependencyID moduleID,
11391206
const ArrayRef<ModuleDependencyID> dependencyIDs);
11401207
/// Resolve this module's cross-import overlay dependencies
1141-
void
1142-
setCrossImportOverlayDependencies(ModuleDependencyID moduleID,
1143-
const ArrayRef<ModuleDependencyID> dependencyIDs);
1208+
void setCrossImportOverlayDependencies(
1209+
ModuleDependencyID moduleID,
1210+
const ModuleDependencyIDCollectionView dependencyIDs);
11441211
/// Add to this module's set of visible Clang modules
11451212
void
11461213
addVisibleClangModules(ModuleDependencyID moduleID,

lib/AST/ModuleDependencies.cpp

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -904,12 +904,13 @@ void ModuleDependenciesCache::setSwiftOverlayDependencies(ModuleDependencyID mod
904904
updatedDependencyInfo.setSwiftOverlayDependencies(dependencyIDs);
905905
updateDependency(moduleID, updatedDependencyInfo);
906906
}
907-
void
908-
ModuleDependenciesCache::setCrossImportOverlayDependencies(ModuleDependencyID moduleID,
909-
const ArrayRef<ModuleDependencyID> dependencyIDs) {
907+
void ModuleDependenciesCache::setCrossImportOverlayDependencies(
908+
ModuleDependencyID moduleID,
909+
const ModuleDependencyIDCollectionView dependencyIDs) {
910910
auto dependencyInfo = findKnownDependency(moduleID);
911911
assert(dependencyInfo.getCrossImportOverlayDependencies().empty());
912-
// Copy the existing info to a mutable one we can then replace it with, after setting its overlay dependencies.
912+
// Copy the existing info to a mutable one we can then replace it with,
913+
// after setting its overlay dependencies.
913914
auto updatedDependencyInfo = dependencyInfo;
914915
updatedDependencyInfo.setCrossImportOverlayDependencies(dependencyIDs);
915916
updateDependency(moduleID, updatedDependencyInfo);
@@ -933,48 +934,33 @@ llvm::StringSet<> &ModuleDependenciesCache::getVisibleClangModules(ModuleDepende
933934
return findKnownDependency(moduleID).getVisibleClangModules();
934935
}
935936

936-
ModuleDependencyIDSetVector
937-
ModuleDependenciesCache::getAllDependencies(const ModuleDependencyID &moduleID) const {
937+
ModuleDependencyIDCollectionView ModuleDependenciesCache::getAllDependencies(
938+
const ModuleDependencyID &moduleID) const {
938939
const auto &moduleInfo = findKnownDependency(moduleID);
939-
ModuleDependencyIDSetVector result;
940-
if (moduleInfo.isSwiftModule()) {
941-
auto swiftImportedDepsRef = moduleInfo.getImportedSwiftDependencies();
942-
auto headerClangDepsRef = moduleInfo.getHeaderClangDependencies();
943-
auto overlayDependenciesRef = moduleInfo.getSwiftOverlayDependencies();
944-
result.insert(swiftImportedDepsRef.begin(),
945-
swiftImportedDepsRef.end());
946-
result.insert(headerClangDepsRef.begin(),
947-
headerClangDepsRef.end());
948-
result.insert(overlayDependenciesRef.begin(),
949-
overlayDependenciesRef.end());
950-
}
951-
952-
if (moduleInfo.isSwiftSourceModule()) {
953-
auto crossImportOverlayDepsRef = moduleInfo.getCrossImportOverlayDependencies();
954-
result.insert(crossImportOverlayDepsRef.begin(),
955-
crossImportOverlayDepsRef.end());
956-
}
957-
958-
auto clangImportedDepsRef = moduleInfo.getImportedClangDependencies();
959-
result.insert(clangImportedDepsRef.begin(),
960-
clangImportedDepsRef.end());
940+
return ModuleDependencyIDCollectionView(
941+
moduleInfo.getImportedSwiftDependencies(),
942+
moduleInfo.getSwiftOverlayDependencies(),
943+
moduleInfo.getCrossImportOverlayDependencies(),
944+
moduleInfo.getHeaderClangDependencies(),
945+
moduleInfo.getImportedClangDependencies());
946+
}
961947

962-
return result;
948+
ModuleDependencyIDCollectionView
949+
ModuleDependenciesCache::getDirectImportedDependencies(
950+
const ModuleDependencyID &moduleID) const {
951+
const auto &moduleInfo = findKnownDependency(moduleID);
952+
return ModuleDependencyIDCollectionView(
953+
moduleInfo.getImportedSwiftDependencies(),
954+
moduleInfo.getImportedClangDependencies());
963955
}
964956

965-
ModuleDependencyIDSetVector
966-
ModuleDependenciesCache::getClangDependencies(const ModuleDependencyID &moduleID) const {
957+
ModuleDependencyIDCollectionView
958+
ModuleDependenciesCache::getAllClangDependencies(
959+
const ModuleDependencyID &moduleID) const {
967960
const auto &moduleInfo = findKnownDependency(moduleID);
968-
ModuleDependencyIDSetVector result;
969-
auto clangImportedDepsRef = moduleInfo.getImportedClangDependencies();
970-
result.insert(clangImportedDepsRef.begin(),
971-
clangImportedDepsRef.end());
972-
if (moduleInfo.isSwiftSourceModule() || moduleInfo.isSwiftBinaryModule()) {
973-
auto headerClangDepsRef = moduleInfo.getHeaderClangDependencies();
974-
result.insert(headerClangDepsRef.begin(),
975-
headerClangDepsRef.end());
976-
}
977-
return result;
961+
return ModuleDependencyIDCollectionView(
962+
moduleInfo.getImportedClangDependencies(),
963+
moduleInfo.getHeaderClangDependencies());
978964
}
979965

980966
llvm::ArrayRef<ModuleDependencyID>

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -953,23 +953,25 @@ ModuleDependencyScanner::resolveImportedModuleDependencies(
953953
allModules.insert(discoveredSwiftModules.begin(),
954954
discoveredSwiftModules.end());
955955

956-
ModuleDependencyIDSetVector discoveredClangModules;
956+
// Resolve all remaining unresolved imports for which no Swift
957+
// module could be found, assuming them to be Clang modules.
958+
// This operation is done by gathering all unresolved import
959+
// identifiers and querying them in-parallel to the Clang
960+
// dependency scanner.
957961
resolveAllClangModuleDependencies(discoveredSwiftModules.getArrayRef(), cache,
958-
discoveredClangModules);
959-
allModules.insert(discoveredClangModules.begin(),
960-
discoveredClangModules.end());
962+
allModules);
961963

962-
ModuleDependencyIDSetVector discoveredHeaderDependencyClangModules;
964+
// For each discovered Swift module which was built with a
965+
// bridging header, scan the header for module dependencies.
966+
// This includes the source module bridging header.
963967
resolveHeaderDependencies(discoveredSwiftModules.getArrayRef(), cache,
964-
discoveredHeaderDependencyClangModules);
965-
allModules.insert(discoveredHeaderDependencyClangModules.begin(),
966-
discoveredHeaderDependencyClangModules.end());
968+
allModules);
967969

968-
ModuleDependencyIDSetVector discoveredSwiftOverlayDependencyModules;
970+
// For each Swift module which imports Clang modules,
971+
// query whether all visible Clang dependencies from such imports
972+
// have a Swift overaly module.
969973
resolveSwiftOverlayDependencies(discoveredSwiftModules.getArrayRef(), cache,
970-
discoveredSwiftOverlayDependencyModules);
971-
allModules.insert(discoveredSwiftOverlayDependencyModules.begin(),
972-
discoveredSwiftOverlayDependencyModules.end());
974+
allModules);
973975

974976
return allModules;
975977
}
@@ -1612,9 +1614,8 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies(
16121614
resolveImportedModuleDependencies(dummyMainID, cache);
16131615

16141616
// Update main module's dependencies to include these new overlays.
1615-
auto newOverlayDeps = cache.getAllDependencies(dummyMainID);
1616-
cache.setCrossImportOverlayDependencies(actualMainID,
1617-
newOverlayDeps.getArrayRef());
1617+
cache.setCrossImportOverlayDependencies(
1618+
actualMainID, cache.getAllDependencies(dummyMainID));
16181619

16191620
// Update the command-line on the main module to
16201621
// disable implicit cross-import overlay search.

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ static bool writeJSONToOutput(DiagnosticEngine &diags,
688688
}
689689

690690
static void
691-
bridgeDependencyIDs(const ArrayRef<ModuleDependencyID> dependencies,
691+
bridgeDependencyIDs(const ModuleDependencyIDCollectionView dependencies,
692692
std::vector<std::string> &bridgedDependencyNames) {
693693
for (const auto &dep : dependencies) {
694694
std::string dependencyKindAndName;
@@ -925,8 +925,7 @@ static swiftscan_dependency_graph_t generateFullDependencyGraph(
925925

926926
// Create a direct dependencies set according to the output format
927927
std::vector<std::string> bridgedDependencyNames;
928-
bridgeDependencyIDs(directDependencies.getArrayRef(),
929-
bridgedDependencyNames);
928+
bridgeDependencyIDs(directDependencies, bridgedDependencyNames);
930929
moduleInfo->direct_dependencies = create_set(bridgedDependencyNames);
931930
moduleInfo->details = getModuleDetails();
932931

0 commit comments

Comments
 (0)