Skip to content

Commit 590331d

Browse files
committed
Moving nested archetype storage into the generic environment.
Instead of storing nested archetypes hierarchically in `ArchetypeType`, store them in a map (indexed by dependent member type) on the generic environment itself. With this, we no longer need to create archetypes for every type along the path, because archetypes are findable via generic environment + interface type.
1 parent 2974f54 commit 590331d

File tree

6 files changed

+73
-122
lines changed

6 files changed

+73
-122
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
7272
Opaque,
7373
};
7474

75+
class NestedTypeStorage;
76+
7577
private:
7678
mutable llvm::PointerIntPair<GenericSignature, 2, Kind> SignatureAndKind{
7779
GenericSignature(), Kind::Normal};
80+
NestedTypeStorage *nestedTypeStorage = nullptr;
7881

7982
friend TrailingObjects;
8083
friend OpaqueTypeArchetypeType;
@@ -93,6 +96,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
9396
/// generic signature.
9497
ArrayRef<Type> getContextTypes() const;
9598

99+
/// Get the nested type storage, allocating it if required.
100+
NestedTypeStorage &getOrCreateNestedTypeStorage();
101+
96102
explicit GenericEnvironment(GenericSignature signature, Kind kind);
97103
explicit GenericEnvironment(
98104
GenericSignature signature, OpaqueTypeDecl *opaque, SubstitutionMap subs);

include/swift/AST/Types.h

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
369369
NumParams : 16
370370
);
371371

372-
SWIFT_INLINE_BITFIELD_FULL(ArchetypeType, TypeBase, 1+1+1+16,
373-
ExpandedNestedTypes : 1,
372+
SWIFT_INLINE_BITFIELD_FULL(ArchetypeType, TypeBase, 1+1+16,
374373
HasSuperclass : 1,
375374
HasLayoutConstraint : 1,
376375
: NumPadBits,
@@ -5395,13 +5394,8 @@ class ArchetypeType : public SubstitutableType,
53955394
return Bits.ArchetypeType.HasLayoutConstraint ? 1 : 0;
53965395
}
53975396
Type InterfaceType;
5398-
MutableArrayRef<std::pair<Identifier, Type>> NestedTypes;
53995397
GenericEnvironment *Environment = nullptr;
54005398

5401-
void populateNestedTypes() const;
5402-
void resolveNestedType(std::pair<Identifier, Type> &nested) const;
5403-
5404-
54055399
// Helper to get the trailing objects of one of the subclasses.
54065400
template<typename Type>
54075401
const Type *getSubclassTrailingObjects() const;
@@ -5455,20 +5449,14 @@ class ArchetypeType : public SubstitutableType,
54555449
return !getConformsTo().empty() || getSuperclass();
54565450
}
54575451

5458-
/// Retrieve the nested type with the given name.
5459-
Type getNestedType(Identifier Name) const;
5452+
/// Retrieve the nested type with the given associated type.
5453+
Type getNestedType(AssociatedTypeDecl *assocType);
54605454

5461-
/// Retrieve the nested type with the given name, if it's already
5462-
/// known.
5455+
/// Retrieve the nested type with the given name.
54635456
///
5464-
/// This is an implementation detail used by the generic signature builder.
5465-
Optional<Type> getNestedTypeIfKnown(Identifier Name) const;
5466-
5467-
/// Check if the archetype contains a nested type with the given name.
5468-
bool hasNestedType(Identifier Name) const;
5469-
5470-
/// Register a nested type with the given name.
5471-
void registerNestedType(Identifier name, Type nested);
5457+
/// This is a slow operation because it must scan all of the protocols to
5458+
/// which the archetype conforms.
5459+
Type getNestedTypeByName(Identifier name);
54725460

54735461
/// Retrieve the parent of this archetype, or null if this is a
54745462
/// primary archetype.

lib/AST/ASTDemangler.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,8 @@ Type ASTBuilder::createDependentMemberType(StringRef member,
638638
auto identifier = Ctx.getIdentifier(member);
639639

640640
if (auto *archetype = base->getAs<ArchetypeType>()) {
641-
if (archetype->hasNestedType(identifier))
642-
return archetype->getNestedType(identifier);
643-
641+
if (Type memberType = archetype->getNestedTypeByName(identifier))
642+
return memberType;
644643
}
645644

646645
if (base->isTypeParameter()) {
@@ -656,8 +655,8 @@ Type ASTBuilder::createDependentMemberType(StringRef member,
656655
auto identifier = Ctx.getIdentifier(member);
657656

658657
if (auto *archetype = base->getAs<ArchetypeType>()) {
659-
if (archetype->hasNestedType(identifier))
660-
return archetype->getNestedType(identifier);
658+
if (auto assocType = protocol->getAssociatedType(identifier))
659+
return archetype->getNestedType(assocType);
661660
}
662661

663662
if (base->isTypeParameter()) {

lib/AST/GenericEnvironment.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,31 @@ Type TypeBase::mapTypeOutOfContext() {
218218
SubstFlags::AllowLoweredTypes);
219219
}
220220

221+
class GenericEnvironment::NestedTypeStorage
222+
: public llvm::DenseMap<CanType, Type> { };
223+
224+
auto GenericEnvironment::getOrCreateNestedTypeStorage() -> NestedTypeStorage & {
225+
if (nestedTypeStorage)
226+
return *nestedTypeStorage;
227+
228+
nestedTypeStorage = new NestedTypeStorage();
229+
ASTContext &ctx = getGenericParams().front()->getASTContext();
230+
ctx.addCleanup([nestedTypeStorage=this->nestedTypeStorage]() {
231+
delete nestedTypeStorage;
232+
});
233+
234+
return *nestedTypeStorage;
235+
}
236+
237+
static Type stripBoundDependentMemberTypes(Type t) {
238+
if (auto *depMemTy = t->getAs<DependentMemberType>()) {
239+
return DependentMemberType::get(
240+
stripBoundDependentMemberTypes(depMemTy->getBase()),
241+
depMemTy->getName());
242+
}
243+
244+
return t;
245+
}
221246
Type
222247
GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
223248
auto genericSig = getGenericSignature();
@@ -248,18 +273,16 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
248273
// First, write an ErrorType to the location where this type is cached,
249274
// to catch re-entrant lookups that might arise from an invalid generic
250275
// signature (eg, <X where X == Array<X>>).
251-
ArchetypeType *parentArchetype = nullptr;
276+
CanDependentMemberType nestedDependentMemberType;
252277
GenericTypeParamType *genericParam = nullptr;
253278
if (auto depMemTy = requirements.anchor->getAs<DependentMemberType>()) {
254-
parentArchetype =
255-
getOrCreateArchetypeFromInterfaceType(depMemTy->getBase())
256-
->castTo<ArchetypeType>();
257-
258-
auto name = depMemTy->getName();
259-
if (auto type = parentArchetype->getNestedTypeIfKnown(name))
260-
return *type;
279+
nestedDependentMemberType = cast<DependentMemberType>(
280+
stripBoundDependentMemberTypes(depMemTy)->getCanonicalType());
281+
auto &entry = getOrCreateNestedTypeStorage()[nestedDependentMemberType];
282+
if (entry)
283+
return entry;
261284

262-
parentArchetype->registerNestedType(name, ErrorType::get(ctx));
285+
entry = ErrorType::get(ctx);
263286
} else {
264287
genericParam = requirements.anchor->castTo<GenericTypeParamType>();
265288
if (auto type = getMappingIfPresent(genericParam))
@@ -277,12 +300,12 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
277300

278301
Type result;
279302

280-
if (parentArchetype) {
303+
if (nestedDependentMemberType) {
281304
auto *depMemTy = requirements.anchor->castTo<DependentMemberType>();
282305
result = NestedArchetypeType::getNew(ctx, depMemTy,
283306
requirements.protos, superclass,
284307
requirements.layout, this);
285-
parentArchetype->registerNestedType(depMemTy->getName(), result);
308+
getOrCreateNestedTypeStorage()[nestedDependentMemberType] = result;
286309
} else if (genericParam->isTypeSequence()) {
287310
result = SequenceArchetypeType::get(ctx, this, genericParam,
288311
requirements.protos, superclass,
@@ -310,21 +333,6 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
310333
return result;
311334
}
312335

313-
void ArchetypeType::resolveNestedType(
314-
std::pair<Identifier, Type> &nested) const {
315-
Type interfaceType = getInterfaceType();
316-
Type memberInterfaceType =
317-
DependentMemberType::get(interfaceType, nested.first);
318-
319-
Type result = getGenericEnvironment()->getOrCreateArchetypeFromInterfaceType(
320-
memberInterfaceType);
321-
322-
assert(!nested.second ||
323-
nested.second->isEqual(result) ||
324-
nested.second->is<ErrorType>());
325-
nested.second = result;
326-
}
327-
328336
Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
329337
if (auto gp = type->getAs<GenericTypeParamType>()) {
330338
// Find the index into the parallel arrays of generic parameters and

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2583,7 +2583,7 @@ static void concretizeNestedTypeFromConcreteParent(
25832583
// Otherwise we have an abstract conformance to an opaque result type.
25842584
assert(conformance.isAbstract());
25852585
auto archetype = concreteParent->castTo<ArchetypeType>();
2586-
witnessType = archetype->getNestedType(assocType->getName());
2586+
witnessType = archetype->getNestedType(assocType);
25872587
}
25882588

25892589
builder.addSameTypeRequirement(

lib/AST/Type.cpp

Lines changed: 21 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3192,7 +3192,6 @@ ArchetypeType::ArchetypeType(TypeKind Kind,
31923192
Environment(Environment)
31933193
{
31943194
// Set up the bits we need for trailing objects to work.
3195-
Bits.ArchetypeType.ExpandedNestedTypes = false;
31963195
Bits.ArchetypeType.HasSuperclass = static_cast<bool>(Superclass);
31973196
Bits.ArchetypeType.HasLayoutConstraint = static_cast<bool>(Layout);
31983197
Bits.ArchetypeType.NumProtocols = ConformsTo.size();
@@ -3695,78 +3694,25 @@ namespace {
36953694
};
36963695
} // end anonymous namespace
36973696

3698-
void ArchetypeType::populateNestedTypes() const {
3699-
if (Bits.ArchetypeType.ExpandedNestedTypes) return;
3700-
3701-
// Collect the set of nested types of this archetype.
3702-
SmallVector<std::pair<Identifier, Type>, 4> nestedTypes;
3703-
llvm::SmallPtrSet<Identifier, 4> knownNestedTypes;
3704-
ProtocolType::visitAllProtocols(getConformsTo(),
3705-
[&](ProtocolDecl *proto) -> bool {
3706-
for (auto assocType : proto->getAssociatedTypeMembers()) {
3707-
if (knownNestedTypes.insert(assocType->getName()).second)
3708-
nestedTypes.push_back({ assocType->getName(), Type() });
3709-
}
3710-
3711-
return false;
3712-
});
3713-
3714-
// Record the nested types.
3715-
auto mutableThis = const_cast<ArchetypeType *>(this);
3716-
3717-
std::sort(nestedTypes.begin(), nestedTypes.end(), OrderArchetypeByName());
3718-
auto &Ctx = mutableThis->getASTContext();
3719-
mutableThis->NestedTypes = Ctx.AllocateCopy(nestedTypes);
3720-
mutableThis->Bits.ArchetypeType.ExpandedNestedTypes = true;
3697+
Type ArchetypeType::getNestedType(AssociatedTypeDecl *assocType) {
3698+
Type interfaceType = getInterfaceType();
3699+
Type memberInterfaceType =
3700+
DependentMemberType::get(interfaceType, assocType->getName());
3701+
return getGenericEnvironment()->getOrCreateArchetypeFromInterfaceType(
3702+
memberInterfaceType);
37213703
}
37223704

3723-
Type ArchetypeType::getNestedType(Identifier Name) const {
3724-
populateNestedTypes();
3725-
3726-
auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name,
3727-
OrderArchetypeByName());
3728-
if (Pos == NestedTypes.end() || Pos->first != Name) {
3729-
return ErrorType::get(const_cast<ArchetypeType *>(this)->getASTContext());
3730-
}
3731-
3732-
// If the type is null, lazily resolve it.
3733-
if (!Pos->second) {
3734-
resolveNestedType(*Pos);
3735-
}
3736-
3737-
return Pos->second;
3738-
}
3739-
3740-
Optional<Type> ArchetypeType::getNestedTypeIfKnown(Identifier Name) const {
3741-
populateNestedTypes();
3742-
3743-
auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name,
3744-
OrderArchetypeByName());
3745-
if (Pos == NestedTypes.end() || Pos->first != Name || !Pos->second)
3746-
return None;
3747-
3748-
return Pos->second;
3749-
}
3750-
3751-
bool ArchetypeType::hasNestedType(Identifier Name) const {
3752-
populateNestedTypes();
3753-
3754-
auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name,
3755-
OrderArchetypeByName());
3756-
return Pos != NestedTypes.end() && Pos->first == Name;
3757-
}
3705+
Type ArchetypeType::getNestedTypeByName(Identifier name) {
3706+
AssociatedTypeDecl *assocType = nullptr;
3707+
ProtocolType::visitAllProtocols(getConformsTo(), [&](ProtocolDecl *proto) {
3708+
assocType = proto->getAssociatedType(name);
3709+
return assocType != nullptr;
3710+
});
37583711

3759-
void ArchetypeType::registerNestedType(Identifier name, Type nested) {
3760-
populateNestedTypes();
3712+
if (assocType)
3713+
return getNestedType(assocType);
37613714

3762-
auto found = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), name,
3763-
OrderArchetypeByName());
3764-
assert(found != NestedTypes.end() && found->first == name &&
3765-
"Unable to find nested type?");
3766-
assert(!found->second ||
3767-
found->second->isEqual(nested) ||
3768-
found->second->is<ErrorType>());
3769-
found->second = nested;
3715+
return Type();
37703716
}
37713717

37723718
AssociatedTypeDecl *NestedArchetypeType::getAssocType() const {
@@ -3974,8 +3920,12 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances,
39743920
// If the parent is an archetype, extract the child archetype with the
39753921
// given name.
39763922
if (auto archetypeParent = substBase->getAs<ArchetypeType>()) {
3977-
if (archetypeParent->hasNestedType(name))
3978-
return archetypeParent->getNestedType(name);
3923+
// if (assocType && !archetypeParent->getSuperclass())
3924+
// return archetypeParent->getNestedType(assocType);
3925+
3926+
// FIXME: This is really slow for the case where we have an associated type.
3927+
if (Type memberArchetypeByName = archetypeParent->getNestedTypeByName(name))
3928+
return memberArchetypeByName;
39793929

39803930
// If looking for an associated type and the archetype is constrained to a
39813931
// class, continue to the default associated type lookup

0 commit comments

Comments
 (0)