Skip to content

Commit 87199d5

Browse files
authored
Merge pull request #26190 from theblixguy/chore/cache-override-signature
[AST] Cache the override generic signatures
2 parents 71577cf + cbdc853 commit 87199d5

File tree

3 files changed

+157
-95
lines changed

3 files changed

+157
-95
lines changed

include/swift/AST/ASTContext.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
#ifndef SWIFT_AST_ASTCONTEXT_H
1818
#define SWIFT_AST_ASTCONTEXT_H
1919

20-
#include "llvm/Support/DataTypes.h"
2120
#include "swift/AST/ClangModuleLoader.h"
2221
#include "swift/AST/Evaluator.h"
22+
#include "swift/AST/GenericSignature.h"
2323
#include "swift/AST/Identifier.h"
2424
#include "swift/AST/SearchPathOptions.h"
2525
#include "swift/AST/Type.h"
@@ -28,13 +28,14 @@
2828
#include "swift/Basic/Malloc.h"
2929
#include "llvm/ADT/ArrayRef.h"
3030
#include "llvm/ADT/DenseMap.h"
31-
#include "llvm/ADT/MapVector.h"
3231
#include "llvm/ADT/IntrusiveRefCntPtr.h"
32+
#include "llvm/ADT/MapVector.h"
3333
#include "llvm/ADT/PointerIntPair.h"
3434
#include "llvm/ADT/SetVector.h"
3535
#include "llvm/ADT/StringMap.h"
3636
#include "llvm/ADT/TinyPtrVector.h"
3737
#include "llvm/Support/Allocator.h"
38+
#include "llvm/Support/DataTypes.h"
3839
#include <functional>
3940
#include <memory>
4041
#include <utility>
@@ -898,6 +899,9 @@ class ASTContext final {
898899
CanGenericSignature getExistentialSignature(CanType existential,
899900
ModuleDecl *mod);
900901

902+
GenericSignature *getOverrideGenericSignature(ValueDecl *base,
903+
ValueDecl *derived);
904+
901905
/// Whether our effective Swift version is at least 'major'.
902906
///
903907
/// This is usually the check you want; for example, when introducing

lib/AST/ASTContext.cpp

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,52 @@ using AssociativityCacheType =
100100
MACRO(NSNumber) \
101101
MACRO(NSValue)
102102

103+
struct OverrideSignatureKey {
104+
GenericSignature *baseMethodSig;
105+
GenericSignature *derivedClassSig;
106+
Type superclassTy;
107+
108+
OverrideSignatureKey(GenericSignature *baseMethodSignature,
109+
GenericSignature *derivedClassSignature,
110+
Type superclassType)
111+
: baseMethodSig(baseMethodSignature),
112+
derivedClassSig(derivedClassSignature), superclassTy(superclassType) {}
113+
};
114+
115+
namespace llvm {
116+
template <> struct DenseMapInfo<OverrideSignatureKey> {
117+
using Type = swift::Type;
118+
using GenericSignature = swift::GenericSignature;
119+
120+
static bool isEqual(const OverrideSignatureKey lhs,
121+
const OverrideSignatureKey rhs) {
122+
return lhs.baseMethodSig == rhs.baseMethodSig &&
123+
lhs.derivedClassSig == rhs.derivedClassSig &&
124+
lhs.superclassTy.getPointer() == rhs.superclassTy.getPointer();
125+
}
126+
127+
static inline OverrideSignatureKey getEmptyKey() {
128+
return OverrideSignatureKey(DenseMapInfo<GenericSignature *>::getEmptyKey(),
129+
DenseMapInfo<GenericSignature *>::getEmptyKey(),
130+
DenseMapInfo<Type>::getEmptyKey());
131+
}
132+
133+
static inline OverrideSignatureKey getTombstoneKey() {
134+
return OverrideSignatureKey(
135+
DenseMapInfo<GenericSignature *>::getTombstoneKey(),
136+
DenseMapInfo<GenericSignature *>::getTombstoneKey(),
137+
DenseMapInfo<Type>::getTombstoneKey());
138+
}
139+
140+
static unsigned getHashValue(const OverrideSignatureKey &Val) {
141+
return hash_combine(
142+
DenseMapInfo<GenericSignature *>::getHashValue(Val.baseMethodSig),
143+
DenseMapInfo<GenericSignature *>::getHashValue(Val.derivedClassSig),
144+
DenseMapInfo<Type>::getHashValue(Val.superclassTy));
145+
}
146+
};
147+
} // namespace llvm
148+
103149
struct ASTContext::Implementation {
104150
Implementation();
105151
~Implementation();
@@ -422,6 +468,8 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
422468
llvm::FoldingSet<SILLayout> SILLayouts;
423469

424470
RC<syntax::SyntaxArena> TheSyntaxArena;
471+
472+
llvm::DenseMap<OverrideSignatureKey, GenericSignature *> overrideSigCache;
425473
};
426474

427475
ASTContext::Implementation::Implementation()
@@ -4337,6 +4385,108 @@ CanGenericSignature ASTContext::getExistentialSignature(CanType existential,
43374385
return genericSig;
43384386
}
43394387

4388+
GenericSignature *ASTContext::getOverrideGenericSignature(ValueDecl *base,
4389+
ValueDecl *derived) {
4390+
auto baseGenericCtx = base->getAsGenericContext();
4391+
auto &ctx = base->getASTContext();
4392+
4393+
if (!baseGenericCtx) {
4394+
return nullptr;
4395+
}
4396+
4397+
auto baseClass = base->getDeclContext()->getSelfClassDecl();
4398+
4399+
if (!baseClass) {
4400+
return nullptr;
4401+
}
4402+
4403+
auto derivedClass = derived->getDeclContext()->getSelfClassDecl();
4404+
auto *baseClassSig = baseClass->getGenericSignature();
4405+
4406+
if (!derivedClass) {
4407+
return nullptr;
4408+
}
4409+
4410+
if (derivedClass->getSuperclass().isNull()) {
4411+
return nullptr;
4412+
}
4413+
4414+
if (derivedClass->getGenericSignature() == nullptr &&
4415+
!baseGenericCtx->isGeneric()) {
4416+
return nullptr;
4417+
}
4418+
4419+
auto subMap = derivedClass->getSuperclass()->getContextSubstitutionMap(
4420+
derivedClass->getModuleContext(), baseClass);
4421+
4422+
if (baseGenericCtx->getGenericSignature() == nullptr) {
4423+
return nullptr;
4424+
}
4425+
unsigned derivedDepth = 0;
4426+
4427+
auto key = OverrideSignatureKey(baseGenericCtx->getGenericSignature(),
4428+
derivedClass->getGenericSignature(),
4429+
derivedClass->getSuperclass());
4430+
4431+
if (getImpl().overrideSigCache.find(key) !=
4432+
getImpl().overrideSigCache.end()) {
4433+
return getImpl().overrideSigCache.lookup(key);
4434+
}
4435+
4436+
if (auto *derivedSig = derivedClass->getGenericSignature())
4437+
derivedDepth = derivedSig->getGenericParams().back()->getDepth() + 1;
4438+
4439+
GenericSignatureBuilder builder(ctx);
4440+
builder.addGenericSignature(derivedClass->getGenericSignature());
4441+
4442+
if (auto derivedGenericCtx = derived->getAsGenericContext()) {
4443+
if (derivedGenericCtx->isGeneric()) {
4444+
for (auto param : *derivedGenericCtx->getGenericParams()) {
4445+
builder.addGenericParameter(param);
4446+
}
4447+
}
4448+
}
4449+
4450+
auto source =
4451+
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
4452+
4453+
unsigned baseDepth = 0;
4454+
4455+
if (baseClassSig) {
4456+
baseDepth = baseClassSig->getGenericParams().back()->getDepth() + 1;
4457+
}
4458+
4459+
auto substFn = [&](SubstitutableType *type) -> Type {
4460+
auto *gp = cast<GenericTypeParamType>(type);
4461+
4462+
if (gp->getDepth() < baseDepth) {
4463+
return Type(gp).subst(subMap);
4464+
}
4465+
4466+
return CanGenericTypeParamType::get(
4467+
gp->getDepth() - baseDepth + derivedDepth, gp->getIndex(), ctx);
4468+
};
4469+
4470+
auto lookupConformanceFn =
4471+
[&](CanType depTy, Type substTy,
4472+
ProtocolDecl *proto) -> Optional<ProtocolConformanceRef> {
4473+
if (auto conf = subMap.lookupConformance(depTy, proto))
4474+
return conf;
4475+
4476+
return ProtocolConformanceRef(proto);
4477+
};
4478+
4479+
for (auto reqt : baseGenericCtx->getGenericSignature()->getRequirements()) {
4480+
if (auto substReqt = reqt.subst(substFn, lookupConformanceFn)) {
4481+
builder.addRequirement(*substReqt, source, nullptr);
4482+
}
4483+
}
4484+
4485+
auto *genericSig = std::move(builder).computeGenericSignature(SourceLoc());
4486+
getImpl().overrideSigCache.insert(std::make_pair(key, genericSig));
4487+
return genericSig;
4488+
}
4489+
43404490
SILLayout *SILLayout::get(ASTContext &C,
43414491
CanGenericSignature Generics,
43424492
ArrayRef<SILField> Fields) {

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -931,98 +931,6 @@ static void checkOverrideAccessControl(ValueDecl *baseDecl, ValueDecl *decl,
931931
}
932932
}
933933

934-
static GenericSignature *getOverrideGenericSignature(ValueDecl *base,
935-
ValueDecl *derived) {
936-
auto baseGenericCtx = base->getAsGenericContext();
937-
auto &ctx = base->getASTContext();
938-
939-
if (!baseGenericCtx) {
940-
return nullptr;
941-
}
942-
943-
auto baseClass = base->getDeclContext()->getSelfClassDecl();
944-
945-
if (!baseClass) {
946-
return nullptr;
947-
}
948-
949-
auto derivedClass = derived->getDeclContext()->getSelfClassDecl();
950-
auto *baseClassSig = baseClass->getGenericSignature();
951-
952-
if (!derivedClass) {
953-
return nullptr;
954-
}
955-
956-
if (derivedClass->getSuperclass().isNull()) {
957-
return nullptr;
958-
}
959-
960-
if (derivedClass->getGenericSignature() == nullptr &&
961-
!baseGenericCtx->isGeneric()) {
962-
return nullptr;
963-
}
964-
965-
auto subMap = derivedClass->getSuperclass()->getContextSubstitutionMap(
966-
derivedClass->getModuleContext(), baseClass);
967-
968-
if (baseGenericCtx->getGenericSignature() == nullptr) {
969-
return nullptr;
970-
}
971-
unsigned derivedDepth = 0;
972-
973-
if (auto *derivedSig = derivedClass->getGenericSignature())
974-
derivedDepth = derivedSig->getGenericParams().back()->getDepth() + 1;
975-
976-
GenericSignatureBuilder builder(ctx);
977-
builder.addGenericSignature(derivedClass->getGenericSignature());
978-
979-
if (auto derivedGenericCtx = derived->getAsGenericContext()) {
980-
if (derivedGenericCtx->isGeneric()) {
981-
for (auto param : *derivedGenericCtx->getGenericParams()) {
982-
builder.addGenericParameter(param);
983-
}
984-
}
985-
}
986-
987-
auto source =
988-
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
989-
990-
unsigned baseDepth = 0;
991-
992-
if (baseClassSig) {
993-
baseDepth = baseClassSig->getGenericParams().back()->getDepth() + 1;
994-
}
995-
996-
auto substFn = [&](SubstitutableType *type) -> Type {
997-
auto *gp = cast<GenericTypeParamType>(type);
998-
999-
if (gp->getDepth() < baseDepth) {
1000-
return Type(gp).subst(subMap);
1001-
}
1002-
1003-
return CanGenericTypeParamType::get(
1004-
gp->getDepth() - baseDepth + derivedDepth, gp->getIndex(), ctx);
1005-
};
1006-
1007-
auto lookupConformanceFn =
1008-
[&](CanType depTy, Type substTy,
1009-
ProtocolDecl *proto) -> Optional<ProtocolConformanceRef> {
1010-
if (auto conf = subMap.lookupConformance(depTy, proto))
1011-
return conf;
1012-
1013-
return ProtocolConformanceRef(proto);
1014-
};
1015-
1016-
for (auto reqt : baseGenericCtx->getGenericSignature()->getRequirements()) {
1017-
if (auto substReqt = reqt.subst(substFn, lookupConformanceFn)) {
1018-
builder.addRequirement(*substReqt, source, nullptr);
1019-
}
1020-
}
1021-
1022-
auto *genericSig = std::move(builder).computeGenericSignature(SourceLoc());
1023-
return genericSig;
1024-
}
1025-
1026934
bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
1027935
OverrideCheckingAttempt attempt) {
1028936
auto &diags = ctx.Diags;
@@ -1045,7 +953,7 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
1045953

1046954
if (baseGenericCtx && derivedGenericCtx) {
1047955
// If the generic signatures are different, then complain
1048-
if (auto newSig = getOverrideGenericSignature(baseDecl, decl)) {
956+
if (auto newSig = ctx.getOverrideGenericSignature(baseDecl, decl)) {
1049957
if (auto derivedSig = derivedGenericCtx->getGenericSignature()) {
1050958
auto requirementsSatisfied =
1051959
derivedSig->requirementsNotSatisfiedBy(newSig).empty();

0 commit comments

Comments
 (0)