Skip to content

Commit d586415

Browse files
authored
Merge pull request swiftlang#77868 from slavapestov/type-alias-type
AST: Two optimizations to speed up compile time
2 parents c0c178f + 302b163 commit d586415

File tree

13 files changed

+204
-123
lines changed

13 files changed

+204
-123
lines changed

include/swift/AST/TypeTransform.h

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -493,43 +493,48 @@ case TypeKind::Id:
493493
if (newParentType && newParentType->isExistentialType())
494494
return newUnderlyingTy;
495495

496-
auto oldSubMap = alias->getSubstitutionMap();
497-
SubstitutionMap newSubMap;
496+
RecursiveTypeProperties substProps;
497+
if (newParentType)
498+
substProps = newParentType->getRecursiveProperties();
498499

499-
// We leave the old behavior behind for ConstraintSystem::openType(), where
500-
// preserving sugar introduces a performance penalty.
501-
if (asDerived().shouldDesugarTypeAliases()) {
502-
for (auto oldReplacementType : oldSubMap.getReplacementTypes()) {
503-
Type newReplacementType = doIt(oldReplacementType, TypePosition::Invariant);
504-
if (!newReplacementType)
505-
return Type();
500+
SmallVector<Type, 4> substArgs;
501+
bool anyChanged = false;
506502

507-
// If anything changed with the replacement type, we lose the sugar.
508-
if (newReplacementType.getPointer() != oldReplacementType.getPointer())
509-
return newUnderlyingTy;
510-
}
503+
const auto transformGenArg = [&](Type arg) -> bool {
504+
Type substArg = doIt(arg, TypePosition::Invariant);
505+
if (!substArg)
506+
return true;
507+
substProps |= substArg->getRecursiveProperties();
508+
substArgs.push_back(substArg);
509+
if (substArg.getPointer() != arg.getPointer())
510+
anyChanged = true;
511511

512-
newSubMap = oldSubMap;
513-
} else {
514-
newSubMap = asDerived().transformSubMap(oldSubMap);
515-
if (oldSubMap && !newSubMap)
512+
return false;
513+
};
514+
515+
for (auto arg : alias->getDirectGenericArgs()) {
516+
if (transformGenArg(arg))
516517
return Type();
517518
}
518519

519520
if (oldParentType.getPointer() == newParentType.getPointer() &&
520521
oldUnderlyingTy.getPointer() == newUnderlyingTy.getPointer() &&
521-
oldSubMap == newSubMap)
522+
!anyChanged)
522523
return t;
523524

525+
// We leave the old behavior behind for ConstraintSystem::openType(), where
526+
// preserving sugar introduces a performance penalty.
527+
if (asDerived().shouldDesugarTypeAliases())
528+
return newUnderlyingTy;
529+
524530
// Don't leave local archetypes and type variables behind in sugar
525531
// if they don't appear in the underlying type, to avoid confusion.
526-
auto props = newSubMap.getRecursiveProperties();
527-
if (props.hasLocalArchetype() && !newUnderlyingTy->hasLocalArchetype())
532+
if (substProps.hasLocalArchetype() != newUnderlyingTy->hasLocalArchetype())
528533
return newUnderlyingTy;
529-
if (props.hasTypeVariable() && !newUnderlyingTy->hasTypeVariable())
534+
if (substProps.hasTypeVariable() != newUnderlyingTy->hasTypeVariable())
530535
return newUnderlyingTy;
531536

532-
return TypeAliasType::get(alias->getDecl(), newParentType, newSubMap,
537+
return TypeAliasType::get(alias->getDecl(), newParentType, substArgs,
533538
newUnderlyingTy);
534539
}
535540

include/swift/AST/Types.h

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -524,14 +524,14 @@ class alignas(1 << TypeAlignInBits) TypeBase
524524
GenericArgCount : 32
525525
);
526526

527-
SWIFT_INLINE_BITFIELD_FULL(TypeAliasType, SugarType, 1+1,
527+
SWIFT_INLINE_BITFIELD_FULL(TypeAliasType, SugarType, 1+1+30,
528528
: NumPadBits,
529529

530530
/// Whether we have a parent type.
531531
HasParent : 1,
532532

533-
/// Whether we have a substitution map.
534-
HasSubstitutionMap : 1
533+
/// The number of generic arguments.
534+
GenericArgCount : 31
535535
);
536536

537537
SWIFT_INLINE_BITFIELD_FULL(IntegerType, TypeBase, 1,
@@ -2253,37 +2253,33 @@ class SugarType : public TypeBase {
22532253
/// set of substitutions to apply to make the type concrete.
22542254
class TypeAliasType final
22552255
: public SugarType, public llvm::FoldingSetNode,
2256-
llvm::TrailingObjects<TypeAliasType, Type, SubstitutionMap>
2256+
llvm::TrailingObjects<TypeAliasType, Type>
22572257
{
22582258
TypeAliasDecl *typealias;
22592259

22602260
friend class ASTContext;
22612261
friend TrailingObjects;
22622262

22632263
TypeAliasType(TypeAliasDecl *typealias, Type parent,
2264-
SubstitutionMap substitutions, Type underlying,
2264+
ArrayRef<Type> genericArgs, Type underlying,
22652265
RecursiveTypeProperties properties);
22662266

22672267
size_t numTrailingObjects(OverloadToken<Type>) const {
2268-
return Bits.TypeAliasType.HasParent ? 1 : 0;
2269-
}
2270-
2271-
size_t numTrailingObjects(OverloadToken<SubstitutionMap>) const {
2272-
return Bits.TypeAliasType.HasSubstitutionMap ? 1 : 0;
2268+
return (Bits.TypeAliasType.HasParent ? 1 : 0) +
2269+
Bits.TypeAliasType.GenericArgCount;
22732270
}
22742271

22752272
public:
22762273
/// Retrieve the generic signature used for substitutions.
2277-
GenericSignature getGenericSignature() const {
2278-
return getSubstitutionMap().getGenericSignature();
2279-
}
2274+
GenericSignature getGenericSignature() const;
22802275

2281-
static TypeAliasType *get(TypeAliasDecl *typealias, Type parent,
2282-
SubstitutionMap substitutions, Type underlying);
2276+
static TypeAliasType *get(TypeAliasDecl *typealias,
2277+
Type parent,
2278+
ArrayRef<Type> genericArgs,
2279+
Type underlying);
22832280

22842281
/// Returns the declaration that declares this type.
22852282
TypeAliasDecl *getDecl() const {
2286-
// Avoid requiring the definition of TypeAliasDecl.
22872283
return typealias;
22882284
}
22892285

@@ -2296,25 +2292,25 @@ class TypeAliasType final
22962292

22972293
/// Retrieve the substitution map applied to the declaration's underlying
22982294
/// to produce the described type.
2299-
SubstitutionMap getSubstitutionMap() const {
2300-
if (!Bits.TypeAliasType.HasSubstitutionMap)
2301-
return SubstitutionMap();
2302-
2303-
return *getTrailingObjects<SubstitutionMap>();
2304-
}
2295+
SubstitutionMap getSubstitutionMap() const;
23052296

23062297
/// Get the direct generic arguments, which correspond to the generic
23072298
/// arguments that are directly applied to the typealias declaration
23082299
/// this type references.
2309-
ArrayRef<Type> getDirectGenericArgs() const;
2300+
ArrayRef<Type> getDirectGenericArgs() const {
2301+
return ArrayRef<Type>(
2302+
getTrailingObjects<Type>() +
2303+
(Bits.TypeAliasType.HasParent ? 1 : 0),
2304+
Bits.TypeAliasType.GenericArgCount);
2305+
}
23102306

23112307
SmallVector<Type, 2> getExpandedGenericArgs();
23122308

23132309
// Support for FoldingSet.
23142310
void Profile(llvm::FoldingSetNodeID &id) const;
23152311

23162312
static void Profile(llvm::FoldingSetNodeID &id, TypeAliasDecl *typealias,
2317-
Type parent, SubstitutionMap substitutions,
2313+
Type parent, ArrayRef<Type> genericArgs,
23182314
Type underlying);
23192315

23202316
// Implement isa/cast/dyncast/etc.

lib/AST/ASTContext.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3380,7 +3380,7 @@ StringRef swift::getSwiftName(KnownFoundationEntity kind) {
33803380
//===----------------------------------------------------------------------===//
33813381

33823382
TypeAliasType::TypeAliasType(TypeAliasDecl *typealias, Type parent,
3383-
SubstitutionMap substitutions,
3383+
ArrayRef<Type> genericArgs,
33843384
Type underlying,
33853385
RecursiveTypeProperties properties)
33863386
: SugarType(TypeKind::TypeAlias, underlying, properties),
@@ -3393,35 +3393,41 @@ TypeAliasType::TypeAliasType(TypeAliasDecl *typealias, Type parent,
33933393
Bits.TypeAliasType.HasParent = false;
33943394
}
33953395

3396-
// Record the substitutions.
3397-
if (substitutions) {
3398-
assert(typealias->getGenericSignature()->isEqual(
3399-
substitutions.getGenericSignature()));
3400-
Bits.TypeAliasType.HasSubstitutionMap = true;
3401-
*getTrailingObjects<SubstitutionMap>() = substitutions;
3396+
auto *params = typealias->getGenericParams();
3397+
unsigned count = genericArgs.size();
3398+
3399+
// Record the generic arguments.
3400+
if (count > 0) {
3401+
ASSERT(params->size() == count);
3402+
Bits.TypeAliasType.GenericArgCount = count;
3403+
std::uninitialized_copy(genericArgs.begin(), genericArgs.end(),
3404+
getTrailingObjects<Type>() +
3405+
(parent ? 1 : 0));
34023406
} else {
3403-
assert(!typealias->isGenericContext());
3404-
Bits.TypeAliasType.HasSubstitutionMap = false;
3407+
ASSERT(params == nullptr);
3408+
Bits.TypeAliasType.GenericArgCount = 0;
34053409
}
34063410
}
34073411

34083412
TypeAliasType *TypeAliasType::get(TypeAliasDecl *typealias, Type parent,
3409-
SubstitutionMap substitutions,
3413+
ArrayRef<Type> genericArgs,
34103414
Type underlying) {
34113415
// Compute the recursive properties.
34123416
//
34133417
auto properties = underlying->getRecursiveProperties();
34143418
if (parent)
34153419
properties |= parent->getRecursiveProperties();
3416-
properties |= substitutions.getRecursiveProperties();
3420+
3421+
for (auto arg : genericArgs)
3422+
properties |= arg->getRecursiveProperties();
34173423

34183424
// Figure out which arena this type will go into.
34193425
auto &ctx = underlying->getASTContext();
34203426
auto arena = getArena(properties);
34213427

34223428
// Profile the type.
34233429
llvm::FoldingSetNodeID id;
3424-
TypeAliasType::Profile(id, typealias, parent, substitutions, underlying);
3430+
TypeAliasType::Profile(id, typealias, parent, genericArgs, underlying);
34253431

34263432
// Did we already record this type?
34273433
void *insertPos;
@@ -3430,29 +3436,29 @@ TypeAliasType *TypeAliasType::get(TypeAliasDecl *typealias, Type parent,
34303436
return result;
34313437

34323438
// Build a new type.
3433-
auto genericSig = substitutions.getGenericSignature();
3434-
auto size = totalSizeToAlloc<Type, SubstitutionMap>(parent ? 1 : 0,
3435-
genericSig ? 1 : 0);
3439+
auto size = totalSizeToAlloc<Type>((parent ? 1 : 0) + genericArgs.size());
34363440
auto mem = ctx.Allocate(size, alignof(TypeAliasType), arena);
3437-
auto result = new (mem) TypeAliasType(typealias, parent, substitutions,
3441+
auto result = new (mem) TypeAliasType(typealias, parent, genericArgs,
34383442
underlying, properties);
34393443
types.InsertNode(result, insertPos);
34403444
return result;
34413445
}
34423446

34433447
void TypeAliasType::Profile(llvm::FoldingSetNodeID &id) const {
3444-
Profile(id, getDecl(), getParent(), getSubstitutionMap(),
3448+
Profile(id, getDecl(), getParent(), getDirectGenericArgs(),
34453449
Type(getSinglyDesugaredType()));
34463450
}
34473451

34483452
void TypeAliasType::Profile(
34493453
llvm::FoldingSetNodeID &id,
34503454
TypeAliasDecl *typealias,
3451-
Type parent, SubstitutionMap substitutions,
3455+
Type parent, ArrayRef<Type> genericArgs,
34523456
Type underlying) {
34533457
id.AddPointer(typealias);
34543458
id.AddPointer(parent.getPointer());
3455-
substitutions.profile(id);
3459+
id.AddInteger(genericArgs.size());
3460+
for (auto arg : genericArgs)
3461+
id.AddPointer(arg.getPointer());
34563462
id.AddPointer(underlying.getPointer());
34573463
}
34583464

lib/AST/ASTMangler.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ static bool shouldMangleAsGeneric(Type type) {
11651165
return false;
11661166

11671167
if (auto typeAlias = dyn_cast<TypeAliasType>(type.getPointer()))
1168-
return !typeAlias->getSubstitutionMap().empty();
1168+
return typeAlias->getDecl()->isGenericContext();
11691169

11701170
return type->isSpecialized();
11711171
}
@@ -1327,13 +1327,28 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
13271327
return appendType(underlyingType, sig, forDecl);
13281328
}
13291329

1330+
// If the type alias is in a generic local context, we don't have enough
1331+
// information to build a proper substitution map because the outer
1332+
// substitutions are not recorded anywhere. In this case, just mangle the
1333+
// type alias's underlying type.
1334+
auto *dc = decl->getDeclContext();
1335+
while (dc->isTypeContext())
1336+
dc = dc->getParent();
1337+
if (dc->isLocalContext() && dc->isGenericContext()) {
1338+
return appendType(underlyingType, sig, forDecl);
1339+
}
1340+
1341+
// If the substitution map is incorrect for some other reason, also skip
1342+
// mangling.
1343+
//
1344+
// FIXME: This shouldn't happen.
13301345
if (decl->getDeclaredInterfaceType()
13311346
.subst(aliasTy->getSubstitutionMap()).getPointer()
13321347
!= aliasTy) {
13331348
return appendType(underlyingType, sig, forDecl);
13341349
}
13351350

1336-
if (aliasTy->getSubstitutionMap()) {
1351+
if (aliasTy->getDecl()->isGenericContext()) {
13371352
// Try to mangle the entire name as a substitution.
13381353
if (tryMangleTypeSubstitution(tybase, sig))
13391354
return;

lib/AST/Type.cpp

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -562,22 +562,34 @@ Type TypeBase::addCurriedSelfType(const DeclContext *dc) {
562562
void TypeBase::getTypeVariables(
563563
SmallPtrSetImpl<TypeVariableType *> &typeVariables) {
564564
// If we know we don't have any type variables, we're done.
565-
if (hasTypeVariable()) {
566-
auto addTypeVariables = [&](Type type) -> bool {
567-
if (auto tv = dyn_cast<TypeVariableType>(type.getPointer())) {
565+
if (!hasTypeVariable())
566+
return;
567+
568+
class Walker : public TypeWalker {
569+
SmallPtrSetImpl<TypeVariableType *> &typeVariables;
570+
571+
public:
572+
explicit Walker(SmallPtrSetImpl<TypeVariableType *> &typeVariables)
573+
: typeVariables(typeVariables) {}
574+
575+
Action walkToTypePre(Type ty) override {
576+
// Skip children that don't contain type variables.
577+
if (!ty->hasTypeVariable())
578+
return Action::SkipNode;
579+
580+
if (auto tv = dyn_cast<TypeVariableType>(ty.getPointer())) {
568581
typeVariables.insert(tv);
569582
}
570583

571-
return false;
572-
};
584+
return Action::Continue;
585+
}
586+
};
573587

574-
// Use Type::findIf() to walk the types, finding type variables along the
575-
// way.
576-
getCanonicalType().findIf(addTypeVariables);
577-
Type(this).findIf(addTypeVariables);
578-
assert((!typeVariables.empty() || hasError()) &&
579-
"Did not find type variables!");
580-
}
588+
Walker walker(typeVariables);
589+
Type(this).walk(walker);
590+
591+
assert((!typeVariables.empty() || hasError()) &&
592+
"Did not find type variables!");
581593
}
582594

583595
static bool isLegalSILType(CanType type);
@@ -1952,12 +1964,33 @@ Type SugarType::getSinglyDesugaredTypeSlow() {
19521964
return UnderlyingType;
19531965
}
19541966

1955-
ArrayRef<Type> TypeAliasType::getDirectGenericArgs() const {
1956-
if (!typealias->isGeneric()) return { };
1967+
GenericSignature TypeAliasType::getGenericSignature() const {
1968+
return typealias->getGenericSignature();
1969+
}
1970+
1971+
SubstitutionMap TypeAliasType::getSubstitutionMap() const {
1972+
auto genericSig = typealias->getGenericSignature();
1973+
if (!genericSig)
1974+
return SubstitutionMap();
1975+
1976+
SubstitutionMap parentSubMap;
1977+
DeclContext *dc = typealias->getDeclContext();
1978+
1979+
if (dc->isLocalContext()) {
1980+
if (auto parentSig = dc->getGenericSignatureOfContext())
1981+
parentSubMap = parentSig->getIdentitySubstitutionMap();
1982+
} else if (auto parent = getParent()) {
1983+
parentSubMap = parent->getContextSubstitutionMap(dc);
1984+
}
1985+
1986+
SmallVector<Type, 4> replacements(
1987+
parentSubMap.getReplacementTypes().begin(),
1988+
parentSubMap.getReplacementTypes().end());
1989+
for (auto arg : getDirectGenericArgs())
1990+
replacements.push_back(arg);
19571991

1958-
// Otherwise, the innermost replacement types are the direct
1959-
// generic arguments.
1960-
return getSubstitutionMap().getInnermostReplacementTypes();
1992+
return SubstitutionMap::get(genericSig, replacements,
1993+
LookUpConformanceInModule());
19611994
}
19621995

19631996
GenericTypeParamType::GenericTypeParamType(GenericTypeParamDecl *param,

0 commit comments

Comments
 (0)