Skip to content

Commit eccdeda

Browse files
authored
Merge pull request #12062 from DougGregor/make-fewer-gsbs
Create fewer generic signature builders
2 parents 4df1586 + 3a3e887 commit eccdeda

25 files changed

+630
-471
lines changed

include/swift/AST/ASTContext.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,16 @@ class ASTContext {
846846
/// not necessarily loaded.
847847
void getVisibleTopLevelClangModules(SmallVectorImpl<clang::Module*> &Modules) const;
848848

849+
private:
850+
/// Register the given generic signature builder to be used as the canonical
851+
/// generic signature builder for the given signature, if we don't already
852+
/// have one.
853+
void registerGenericSignatureBuilder(GenericSignature *sig,
854+
ModuleDecl &module,
855+
GenericSignatureBuilder &&builder);
856+
friend class GenericSignatureBuilder;
857+
858+
public:
849859
/// Retrieve or create the stored generic signature builder for the given
850860
/// canonical generic signature and module.
851861
GenericSignatureBuilder *getOrCreateGenericSignatureBuilder(CanGenericSignature sig,

include/swift/AST/Decl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4591,7 +4591,7 @@ class ParamDecl : public VarDecl {
45914591
/// Clone constructor, allocates a new ParamDecl identical to the first.
45924592
/// Intentionally not defined as a typical copy constructor to avoid
45934593
/// accidental copies.
4594-
ParamDecl(ParamDecl *PD);
4594+
ParamDecl(ParamDecl *PD, bool withTypes);
45954595

45964596
/// Retrieve the argument (API) name for this function parameter.
45974597
Identifier getArgumentName() const { return ArgumentName; }

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,14 @@ class GenericSignatureBuilder {
215215
/// a superclass requirement.
216216
bool isConformanceSatisfiedBySuperclass(ProtocolDecl *proto) const;
217217

218+
/// Lookup a nested type with the given name within this equivalence
219+
/// class.
220+
///
221+
/// \param otherConcreteTypes If non-null, will be filled in the all of the
222+
/// concrete types we found (other than the result) with the same name.
223+
TypeDecl *lookupNestedType(Identifier name,
224+
SmallVectorImpl<TypeDecl *> *otherConcreteTypes);
225+
218226
/// Dump a debugging representation of this equivalence class.
219227
void dump(llvm::raw_ostream &out) const;
220228

@@ -232,6 +240,17 @@ class GenericSignatureBuilder {
232240
/// anchor was cached.
233241
unsigned numMembers;
234242
} archetypeAnchorCache;
243+
244+
/// Describes a cached nested type.
245+
struct CachedNestedType {
246+
unsigned numConformancesPresent;
247+
CanType superclassPresent;
248+
llvm::TinyPtrVector<TypeDecl *> types;
249+
};
250+
251+
/// Cached nested-type information, which contains the best declaration
252+
/// for a given name.
253+
llvm::SmallDenseMap<Identifier, CachedNestedType> nestedTypeNameCache;
235254
};
236255

237256
friend class RequirementSource;
@@ -522,9 +541,6 @@ class GenericSignatureBuilder {
522541
/// \brief Add all of a generic signature's parameters and requirements.
523542
void addGenericSignature(GenericSignature *sig);
524543

525-
/// \brief Build the generic signature.
526-
GenericSignature *getGenericSignature();
527-
528544
/// Infer requirements from the given type, recursively.
529545
///
530546
/// This routine infers requirements from a type that occurs within the
@@ -558,11 +574,14 @@ class GenericSignatureBuilder {
558574
/// \brief Finalize the set of requirements and compute the generic
559575
/// signature.
560576
///
561-
/// After this point, one cannot introduce new requirements.
577+
/// After this point, one cannot introduce new requirements, and the
578+
/// generic signature builder no longer has valid state.
562579
GenericSignature *computeGenericSignature(
580+
ModuleDecl &module,
563581
SourceLoc loc,
564-
bool allowConcreteGenericParams = false);
582+
bool allowConcreteGenericParams = false) &&;
565583

584+
private:
566585
/// Finalize the set of requirements, performing any remaining checking
567586
/// required before generating archetypes.
568587
///
@@ -572,6 +591,7 @@ class GenericSignatureBuilder {
572591
ArrayRef<GenericTypeParamType *> genericParams,
573592
bool allowConcreteGenericParams=false);
574593

594+
public:
575595
/// Process any delayed requirements that can be handled now.
576596
void processDelayedRequirements();
577597

@@ -1475,6 +1495,12 @@ class GenericSignatureBuilder::PotentialArchetype {
14751495
return pa->parentOrBuilder.get<GenericSignatureBuilder *>();
14761496
}
14771497

1498+
// Replace the generic signature builder.
1499+
void replaceBuilder(GenericSignatureBuilder *builder) {
1500+
assert(parentOrBuilder.is<GenericSignatureBuilder *>());
1501+
parentOrBuilder = builder;
1502+
}
1503+
14781504
friend class GenericSignatureBuilder;
14791505
friend class GenericSignature;
14801506

@@ -1490,6 +1516,12 @@ class GenericSignatureBuilder::PotentialArchetype {
14901516
return parentOrBuilder.dyn_cast<PotentialArchetype *>();
14911517
}
14921518

1519+
/// Retrieve the type declaration to which this nested type was resolved.
1520+
TypeDecl *getResolvedType() const {
1521+
assert(getParent() && "Not an associated type");
1522+
return identifier.assocTypeOrConcrete;
1523+
}
1524+
14931525
/// Retrieve the associated type to which this potential archetype
14941526
/// has been resolved.
14951527
AssociatedTypeDecl *getResolvedAssociatedType() const {
@@ -1632,13 +1664,8 @@ class GenericSignatureBuilder::PotentialArchetype {
16321664
ArchetypeResolutionKind kind,
16331665
GenericSignatureBuilder &builder);
16341666

1635-
/// \brief Retrieve (or create) a nested type with a known associated type.
1636-
PotentialArchetype *getNestedType(AssociatedTypeDecl *assocType,
1637-
GenericSignatureBuilder &builder);
1638-
1639-
/// \brief Retrieve (or create) a nested type with a known concrete type
1640-
/// declaration.
1641-
PotentialArchetype *getNestedType(TypeDecl *concreteDecl,
1667+
/// \brief Retrieve (or create) a nested type with a known type.
1668+
PotentialArchetype *getNestedType(TypeDecl *type,
16421669
GenericSignatureBuilder &builder);
16431670

16441671
/// \brief Retrieve (or create) a nested type that is the current best
@@ -1658,8 +1685,8 @@ class GenericSignatureBuilder::PotentialArchetype {
16581685
/// type or typealias of the given protocol, unless the \c kind implies that
16591686
/// a potential archetype should not be created if it's missing.
16601687
PotentialArchetype *updateNestedTypeForConformance(
1661-
PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
1662-
ArchetypeResolutionKind kind);
1688+
TypeDecl *type,
1689+
ArchetypeResolutionKind kind);
16631690

16641691
/// Update the named nested type when we know this type conforms to the given
16651692
/// protocol.

include/swift/AST/ParameterList.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,15 @@ class alignas(ParamDecl *) ParameterList final :
128128
Implicit = 0x01,
129129
/// The cloned pattern is for an inherited constructor; mark default
130130
/// arguments as inherited, and mark unnamed arguments as named.
131-
Inherited = 0x02
131+
Inherited = 0x02,
132+
/// The cloned pattern will strip type information.
133+
WithoutTypes = 0x04,
132134
};
133-
135+
136+
friend OptionSet<CloneFlags> operator|(CloneFlags flag1, CloneFlags flag2) {
137+
return OptionSet<CloneFlags>(flag1) | flag2;
138+
}
139+
134140
/// Make a duplicate copy of this parameter list. This allocates copies of
135141
/// the ParamDecls, so they can be reparented into a new DeclContext.
136142
ParameterList *clone(const ASTContext &C,

lib/AST/ASTContext.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "clang/Lex/HeaderSearch.h"
4343
#include "clang/Lex/Preprocessor.h"
4444
#include "llvm/ADT/DenseMap.h"
45+
#include "llvm/ADT/Statistic.h"
4546
#include "llvm/ADT/StringMap.h"
4647
#include "llvm/ADT/StringSwitch.h"
4748
#include "llvm/Support/Allocator.h"
@@ -51,6 +52,12 @@
5152

5253
using namespace swift;
5354

55+
#define DEBUG_TYPE "ASTContext"
56+
STATISTIC(NumRegisteredGenericSignatureBuilders,
57+
"# of generic signature builders successfully registered");
58+
STATISTIC(NumRegisteredGenericSignatureBuildersAlready,
59+
"# of generic signature builders already registered");
60+
5461
/// Define this to 1 to enable expensive assertions of the
5562
/// GenericSignatureBuilder.
5663
#define SWIFT_GSB_EXPENSIVE_ASSERTIONS 0
@@ -1421,6 +1428,22 @@ void ASTContext::getVisibleTopLevelClangModules(
14211428
collectAllModules(Modules);
14221429
}
14231430

1431+
void ASTContext::registerGenericSignatureBuilder(
1432+
GenericSignature *sig,
1433+
ModuleDecl &module,
1434+
GenericSignatureBuilder &&builder) {
1435+
auto canSig = sig->getCanonicalSignature();
1436+
auto known = Impl.GenericSignatureBuilders.find({canSig, &module});
1437+
if (known != Impl.GenericSignatureBuilders.end()) {
1438+
++NumRegisteredGenericSignatureBuildersAlready;
1439+
return;
1440+
}
1441+
1442+
++NumRegisteredGenericSignatureBuilders;
1443+
Impl.GenericSignatureBuilders[{canSig, &module}] =
1444+
llvm::make_unique<GenericSignatureBuilder>(std::move(builder));
1445+
}
1446+
14241447
GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
14251448
CanGenericSignature sig,
14261449
ModuleDecl *mod) {
@@ -4589,7 +4612,7 @@ CanGenericSignature ASTContext::getExistentialSignature(CanType existential,
45894612
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
45904613
builder.addRequirement(requirement, source, nullptr);
45914614

4592-
CanGenericSignature genericSig(builder.computeGenericSignature(SourceLoc()));
4615+
CanGenericSignature genericSig(std::move(builder).computeGenericSignature(*mod, SourceLoc()));
45934616

45944617
auto result = Impl.ExistentialSignatures.insert(
45954618
std::make_pair(existential, genericSig));

lib/AST/Builtins.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,9 @@ namespace {
491491
Builder.addGenericParameter(gp);
492492
}
493493

494-
auto GenericSig = Builder.computeGenericSignature(SourceLoc());
494+
auto GenericSig =
495+
std::move(Builder).computeGenericSignature(*ctx.TheBuiltinModule,
496+
SourceLoc());
495497
GenericEnv = GenericSig->createGenericEnvironment(*ctx.TheBuiltinModule);
496498
}
497499

lib/AST/Decl.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3419,7 +3419,8 @@ void ProtocolDecl::computeRequirementSignature() {
34193419
nullptr);
34203420

34213421
// Compute and record the signature.
3422-
auto requirementSig = builder.computeGenericSignature(SourceLoc());
3422+
auto requirementSig =
3423+
std::move(builder).computeGenericSignature(*module, SourceLoc());
34233424
RequirementSignature = requirementSig->getRequirements().data();
34243425
assert(RequirementSignature != nullptr);
34253426
NumRequirementsInSignature = requirementSig->getRequirements().size();
@@ -4217,18 +4218,22 @@ ParamDecl::ParamDecl(Specifier specifier,
42174218

42184219
/// Clone constructor, allocates a new ParamDecl identical to the first.
42194220
/// Intentionally not defined as a copy constructor to avoid accidental copies.
4220-
ParamDecl::ParamDecl(ParamDecl *PD)
4221+
ParamDecl::ParamDecl(ParamDecl *PD, bool withTypes)
42214222
: VarDecl(DeclKind::Param, /*IsStatic*/false, PD->getSpecifier(),
42224223
/*IsCaptureList*/false, PD->getNameLoc(), PD->getName(),
4223-
PD->hasType() ? PD->getType() : Type(), PD->getDeclContext()),
4224+
PD->hasType() && withTypes? PD->getType() : Type(),
4225+
PD->getDeclContext()),
42244226
ArgumentName(PD->getArgumentName()),
42254227
ArgumentNameLoc(PD->getArgumentNameLoc()),
42264228
SpecifierLoc(PD->getSpecifierLoc()),
42274229
DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()),
42284230
IsTypeLocImplicit(PD->IsTypeLocImplicit),
42294231
defaultArgumentKind(PD->defaultArgumentKind) {
42304232
typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
4231-
if (PD->hasInterfaceType())
4233+
if (!withTypes && typeLoc.getTypeRepr())
4234+
typeLoc.setType(Type());
4235+
4236+
if (withTypes && PD->hasInterfaceType())
42324237
setInterfaceType(PD->getInterfaceType());
42334238
}
42344239

0 commit comments

Comments
 (0)