Skip to content

Commit c13c752

Browse files
authored
Merge pull request #23025 from davezarzycki/local_DependentMemberType_caching
[GSB] NFC: Improve performance with local DependentMemberType caching
2 parents 038a3a6 + 8876c9e commit c13c752

File tree

2 files changed

+49
-15
lines changed

2 files changed

+49
-15
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,11 @@ class GenericSignatureBuilder::RequirementSource final
935935
AssociatedTypeDecl,
936936
};
937937

938+
/// Cache DependentMemberType results instead of calling
939+
/// DependentMemberType::get(). The much smaller hash table is more
940+
/// processor cache efficient.
941+
mutable llvm::DenseMap<Type, Type> ReplacedSelfCache;
942+
938943
/// The kind of storage we have.
939944
const StorageKind storageKind;
940945

@@ -954,8 +959,9 @@ class GenericSignatureBuilder::RequirementSource final
954959
/// A protocol conformance used to satisfy the requirement.
955960
void *conformance;
956961

957-
/// An associated type to which a requirement is being applied.
958-
AssociatedTypeDecl *assocType;
962+
/// A precomputed dependent member of an associated type to which a
963+
/// requirement is being applied.
964+
DependentMemberType *dependentMember;
959965
} storage;
960966

961967
friend TrailingObjects;
@@ -1093,7 +1099,8 @@ class GenericSignatureBuilder::RequirementSource final
10931099
assert(isAcceptableStorageKind(kind, storageKind) &&
10941100
"RequirementSource kind/storageKind mismatch");
10951101

1096-
storage.assocType = assocType;
1102+
auto ty = assocType->getDeclaredInterfaceType();
1103+
storage.dependentMember = cast<DependentMemberType>(ty.getPointer());
10971104
}
10981105

10991106
RequirementSource(Kind kind, const RequirementSource *parent)
@@ -1315,11 +1322,18 @@ class GenericSignatureBuilder::RequirementSource final
13151322
return ProtocolConformanceRef::getFromOpaqueValue(storage.conformance);
13161323
}
13171324

1325+
/// Retrieve the precomputed dependent member for the associated type
1326+
/// declaration for this requirement, if there is one.
1327+
DependentMemberType *getDependentMember() const {
1328+
if (storageKind != StorageKind::AssociatedTypeDecl) return nullptr;
1329+
return storage.dependentMember;
1330+
}
1331+
13181332
/// Retrieve the associated type declaration for this requirement, if there
13191333
/// is one.
13201334
AssociatedTypeDecl *getAssociatedType() const {
13211335
if (storageKind != StorageKind::AssociatedTypeDecl) return nullptr;
1322-
return storage.assocType;
1336+
return storage.dependentMember->getAssocType();
13231337
}
13241338

13251339
/// Profiling support for \c FoldingSet.
@@ -1558,6 +1572,11 @@ class GenericSignatureBuilder::PotentialArchetype {
15581572
/// that share a name.
15591573
llvm::MapVector<Identifier, StoredNestedType> NestedTypes;
15601574

1575+
/// Cache DependentMemberType results instead of calling
1576+
/// DependentMemberType::get(). The much smaller hash table is more
1577+
/// processor cache efficient.
1578+
mutable llvm::DenseMap<Type, DependentMemberType*> CachedDMTs;
1579+
15611580
/// Construct a new potential archetype for a concrete declaration.
15621581
PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
15631582
: parentOrContext(parent), identifier(assocType) {
@@ -1597,6 +1616,14 @@ class GenericSignatureBuilder::PotentialArchetype {
15971616
return identifier.assocType;
15981617
}
15991618

1619+
/// Retrieve the type declaration to which this nested type was resolved.
1620+
DependentMemberType *getResolvedDependentMemberType(Type Parent) const {
1621+
auto *&known = CachedDMTs[Parent];
1622+
if (!known)
1623+
known = DependentMemberType::get(Parent, getResolvedType());
1624+
return known;
1625+
}
1626+
16001627
/// Determine whether this is a generic parameter.
16011628
bool isGenericParam() const {
16021629
return parentOrContext.is<ASTContext *>();

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ const void *RequirementSource::getOpaqueStorage1() const {
818818
return storage.type;
819819

820820
case StorageKind::AssociatedTypeDecl:
821-
return storage.assocType;
821+
return storage.dependentMember;
822822
}
823823

824824
llvm_unreachable("Unhandled StorageKind in switch.");
@@ -918,11 +918,16 @@ bool RequirementSource::isSelfDerivedSource(GenericSignatureBuilder &builder,
918918
/// the nested type. This limited operation makes sure that it does not
919919
/// create any new potential archetypes along the way, so it should only be
920920
/// used in cases where we're reconstructing something that we know exists.
921-
static Type replaceSelfWithType(Type selfType, Type depTy) {
921+
static Type replaceSelfWithType(llvm::DenseMap<Type, Type> &cache,
922+
Type selfType, Type depTy) {
922923
if (auto depMemTy = depTy->getAs<DependentMemberType>()) {
923-
Type baseType = replaceSelfWithType(selfType, depMemTy->getBase());
924+
Type baseType = replaceSelfWithType(cache, selfType, depMemTy->getBase());
924925
assert(depMemTy->getAssocType() && "Missing associated type");
925-
return DependentMemberType::get(baseType, depMemTy->getAssocType());
926+
auto &known = cache[baseType];
927+
if (!known) {
928+
known = DependentMemberType::get(baseType, depMemTy->getAssocType());
929+
}
930+
return known;
926931
}
927932

928933
assert(depTy->is<GenericTypeParamType>() && "missing Self?");
@@ -1366,8 +1371,8 @@ RequirementSource::visitPotentialArchetypesAlongPath(
13661371

13671372
if (visitor(parentType, this)) return nullptr;
13681373

1369-
return replaceSelfWithType(parentType,
1370-
getAssociatedType()->getDeclaredInterfaceType());
1374+
return replaceSelfWithType(ReplacedSelfCache,
1375+
parentType, getDependentMember());
13711376
}
13721377

13731378
case RequirementSource::NestedTypeNameMatch:
@@ -1402,7 +1407,8 @@ RequirementSource::visitPotentialArchetypesAlongPath(
14021407

14031408
if (visitor(parentType, this)) return nullptr;
14041409

1405-
return replaceSelfWithType(parentType, getStoredType());
1410+
return replaceSelfWithType(ReplacedSelfCache,
1411+
parentType, getStoredType());
14061412
}
14071413
}
14081414
llvm_unreachable("unhandled kind");
@@ -1436,7 +1442,7 @@ ProtocolDecl *RequirementSource::getProtocolDecl() const {
14361442
return getProtocolConformance().getRequirement();
14371443

14381444
case StorageKind::AssociatedTypeDecl:
1439-
return storage.assocType->getProtocol();
1445+
return storage.dependentMember->getAssocType()->getProtocol();
14401446
}
14411447

14421448
llvm_unreachable("Unhandled StorageKind in switch.");
@@ -1607,8 +1613,9 @@ void RequirementSource::print(llvm::raw_ostream &out,
16071613
}
16081614

16091615
case StorageKind::AssociatedTypeDecl:
1610-
out << " (" << storage.assocType->getProtocol()->getName()
1611-
<< "::" << storage.assocType->getName() << ")";
1616+
auto assocType = storage.dependentMember->getAssocType();
1617+
out << " (" << assocType->getProtocol()->getName()
1618+
<< "::" << assocType->getName() << ")";
16121619
break;
16131620
}
16141621

@@ -2935,7 +2942,7 @@ Type GenericSignatureBuilder::PotentialArchetype::getDependentType(
29352942

29362943
// If we've resolved to an associated type, use it.
29372944
if (auto assocType = getResolvedType())
2938-
return DependentMemberType::get(parentType, assocType);
2945+
return getResolvedDependentMemberType(parentType);
29392946

29402947
return DependentMemberType::get(parentType, getNestedName());
29412948
}

0 commit comments

Comments
 (0)