Skip to content

Commit 8d05d79

Browse files
committed
AST: Cache substituted substitution maps inside the InFlightSubstitution
A substitution map contains conformances, and a conformance can contain a substitution map. This will always be a DAG, but not a tree, and to avoid exponential blowup in certain edge cases, let's cache the work to avoid visiting the same substitution map repeatedly, if multiple conformances refer to the same substitution map.
1 parent b70f8a8 commit 8d05d79

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

include/swift/AST/InFlightSubstitution.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@
2323
#define SWIFT_AST_INFLIGHTSUBSTITUTION_H
2424

2525
#include "swift/AST/SubstitutionMap.h"
26+
#include "llvm/ADT/DenseMap.h"
2627

2728
namespace swift {
2829
class SubstitutionMap;
2930

3031
class InFlightSubstitution {
32+
friend class SubstitutionMap;
33+
3134
TypeSubstitutionFn BaselineSubstType;
3235
LookupConformanceFn BaselineLookupConformance;
3336
SubstOptions Options;
@@ -41,6 +44,7 @@ class InFlightSubstitution {
4144
unsigned expansionIndex = 0;
4245
};
4346
llvm::SmallVector<ActivePackExpansion, 4> ActivePackExpansions;
47+
llvm::SmallDenseMap<SubstitutionMap, SubstitutionMap, 2> SubMaps;
4448

4549
Type projectLaneFromPackType(
4650
Type substType, unsigned level);

lib/AST/SubstitutionMap.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,13 @@ SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
325325
SubstitutionMap SubstitutionMap::subst(InFlightSubstitution &IFS) const {
326326
if (empty()) return SubstitutionMap();
327327

328+
// FIXME: Get this caching working with pack expansions as well.
329+
if (IFS.ActivePackExpansions.empty()) {
330+
auto found = IFS.SubMaps.find(*this);
331+
if (found != IFS.SubMaps.end())
332+
return found->second;
333+
}
334+
328335
SmallVector<Type, 4> newSubs;
329336
for (Type type : getReplacementTypes()) {
330337
newSubs.push_back(type.subst(IFS));
@@ -345,7 +352,12 @@ SubstitutionMap SubstitutionMap::subst(InFlightSubstitution &IFS) const {
345352
}
346353

347354
assert(oldConformances.empty());
348-
return SubstitutionMap(genericSig, newSubs, newConformances);
355+
auto result = SubstitutionMap(genericSig, newSubs, newConformances);
356+
357+
if (IFS.ActivePackExpansions.empty())
358+
(void) IFS.SubMaps.insert(std::make_pair(*this, result));
359+
360+
return result;
349361
}
350362

351363
SubstitutionMap

0 commit comments

Comments
 (0)