Skip to content

Commit 07f5029

Browse files
authored
Merge pull request #13663 from davezarzycki/nfc_refactor_typenode_hierarchy
[AST] Perf: Make generic decl types share field offsets and fast casting logic
2 parents 598c385 + 2882e16 commit 07f5029

File tree

4 files changed

+109
-116
lines changed

4 files changed

+109
-116
lines changed

include/swift/AST/TypeNodes.def

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,22 @@ ABSTRACT_TYPE(ReferenceStorage, Type)
107107
ARTIFICIAL_TYPE(UnmanagedStorage, ReferenceStorageType)
108108
ARTIFICIAL_TYPE(WeakStorage, ReferenceStorageType)
109109
TYPE_RANGE(ReferenceStorage, UnownedStorage, WeakStorage)
110-
ABSTRACT_TYPE(Nominal, Type)
111-
TYPE(Enum, NominalType)
112-
TYPE(Struct, NominalType)
113-
TYPE(Class, NominalType)
114-
TYPE(Protocol, NominalType)
115-
TYPE_RANGE(Nominal, Enum, Protocol)
110+
ABSTRACT_TYPE(AnyGeneric, Type)
111+
ABSTRACT_TYPE(NominalOrBoundGenericNominal, Type)
112+
ABSTRACT_TYPE(Nominal, Type)
113+
TYPE(Enum, NominalType)
114+
TYPE(Struct, NominalType)
115+
TYPE(Class, NominalType)
116+
TYPE(Protocol, NominalType)
117+
TYPE_RANGE(Nominal, Enum, Protocol)
118+
ABSTRACT_TYPE(BoundGeneric, Type)
119+
TYPE(BoundGenericClass, BoundGenericType)
120+
TYPE(BoundGenericEnum, BoundGenericType)
121+
TYPE(BoundGenericStruct, BoundGenericType)
122+
TYPE_RANGE(BoundGeneric, BoundGenericClass, BoundGenericStruct)
123+
TYPE_RANGE(NominalOrBoundGenericNominal, Enum, BoundGenericStruct)
124+
UNCHECKED_TYPE(UnboundGeneric, Type)
125+
TYPE_RANGE(AnyGeneric, Enum, UnboundGeneric)
116126
ABSTRACT_TYPE(AnyMetatype, Type)
117127
TYPE(Metatype, AnyMetatypeType)
118128
TYPE(ExistentialMetatype, AnyMetatypeType)
@@ -140,12 +150,6 @@ SUGARED_TYPE(Dictionary, Type)
140150
TYPE(ProtocolComposition, Type)
141151
TYPE(LValue, Type)
142152
TYPE(InOut, Type)
143-
UNCHECKED_TYPE(UnboundGeneric, Type)
144-
ABSTRACT_TYPE(BoundGeneric, Type)
145-
TYPE(BoundGenericClass, BoundGenericType)
146-
TYPE(BoundGenericEnum, BoundGenericType)
147-
TYPE(BoundGenericStruct, BoundGenericType)
148-
TYPE_RANGE(BoundGeneric, BoundGenericClass, BoundGenericStruct)
149153
UNCHECKED_TYPE(TypeVariable, Type)
150154
LAST_TYPE(TypeVariable)
151155

include/swift/AST/Types.h

Lines changed: 89 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,76 @@ class alignas(1 << TypeAlignInBits) TypeBase {
10271027
void *operator new(size_t Bytes, void *Mem) throw() { return Mem; }
10281028
};
10291029

1030+
/// AnyGenericType - This abstract class helps types ensure that fields
1031+
/// exist at the same offset in memory to improve code generation of the
1032+
/// compiler itself.
1033+
class AnyGenericType : public TypeBase {
1034+
friend class NominalOrBoundGenericNominalType;
1035+
1036+
/// TheDecl - This is the TypeDecl which declares the given type. It
1037+
/// specifies the name and other useful information about this type.
1038+
union {
1039+
GenericTypeDecl *GenDecl;
1040+
NominalTypeDecl *NomDecl;
1041+
};
1042+
1043+
/// \brief The type of the parent, in which this type is nested.
1044+
Type Parent;
1045+
1046+
template <typename... Args>
1047+
AnyGenericType(NominalTypeDecl *TheDecl, Type Parent, Args &&...args)
1048+
: TypeBase(std::forward<Args>(args)...), NomDecl(TheDecl), Parent(Parent) {}
1049+
1050+
protected:
1051+
template <typename... Args>
1052+
AnyGenericType(GenericTypeDecl *TheDecl, Type Parent, Args &&...args)
1053+
: TypeBase(std::forward<Args>(args)...), GenDecl(TheDecl), Parent(Parent) {}
1054+
1055+
public:
1056+
1057+
/// \brief Returns the declaration that declares this type.
1058+
GenericTypeDecl *getDecl() const { return GenDecl; }
1059+
1060+
/// \brief Returns the type of the parent of this type. This will
1061+
/// be null for top-level types or local types, and for non-generic types
1062+
/// will simply be the same as the declared type of the declaration context
1063+
/// of TheDecl. For types nested within generic types, however, this will
1064+
/// involve \c BoundGenericType nodes that provide context for the nested
1065+
/// type, e.g., the type Dictionary<String, Int>.ItemRange would be
1066+
/// represented as a NominalType with Dictionary<String, Int> as its parent
1067+
/// type.
1068+
Type getParent() const { return Parent; }
1069+
1070+
// Implement isa/cast/dyncast/etc.
1071+
static bool classof(const TypeBase *T) {
1072+
return T->getKind() >= TypeKind::First_AnyGenericType &&
1073+
T->getKind() <= TypeKind::Last_AnyGenericType;
1074+
}
1075+
};
1076+
BEGIN_CAN_TYPE_WRAPPER(AnyGenericType, Type)
1077+
PROXY_CAN_TYPE_SIMPLE_GETTER(getParent)
1078+
END_CAN_TYPE_WRAPPER(AnyGenericType, Type)
1079+
1080+
/// NominalOrBoundGenericNominal - This abstract class helps types ensure that
1081+
/// fields exist at the same offset in memory to improve code generation of the
1082+
/// compiler itself.
1083+
class NominalOrBoundGenericNominalType : public AnyGenericType {
1084+
public:
1085+
template <typename... Args>
1086+
NominalOrBoundGenericNominalType(Args &&...args)
1087+
: AnyGenericType(std::forward<Args>(args)...) {}
1088+
1089+
/// \brief Returns the declaration that declares this type.
1090+
NominalTypeDecl *getDecl() const { return NomDecl; }
1091+
1092+
// Implement isa/cast/dyncast/etc.
1093+
static bool classof(const TypeBase *T) {
1094+
return T->getKind() >= TypeKind::First_NominalOrBoundGenericNominalType &&
1095+
T->getKind() <= TypeKind::Last_NominalOrBoundGenericNominalType;
1096+
}
1097+
};
1098+
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalOrBoundGenericNominalType, AnyGenericType)
1099+
10301100
/// ErrorType - This represents a type that was erroneously constructed. This
10311101
/// is produced when parsing types and when name binding type aliases, and is
10321102
/// installed in declaration that use these erroneous types. All uses of a
@@ -1681,37 +1751,19 @@ END_CAN_TYPE_WRAPPER(TupleType, Type)
16811751

16821752
/// UnboundGenericType - Represents a generic type where the type arguments have
16831753
/// not yet been resolved.
1684-
class UnboundGenericType : public TypeBase, public llvm::FoldingSetNode {
1685-
GenericTypeDecl *TheDecl;
1686-
1687-
/// \brief The type of the parent, in which this type is nested.
1688-
Type Parent;
1689-
1754+
class UnboundGenericType : public AnyGenericType,
1755+
public llvm::FoldingSetNode {
16901756
private:
16911757
UnboundGenericType(GenericTypeDecl *TheDecl, Type Parent, const ASTContext &C,
16921758
RecursiveTypeProperties properties)
1693-
: TypeBase(TypeKind::UnboundGeneric,
1694-
(!Parent || Parent->isCanonical())? &C : nullptr,
1695-
properties | RecursiveTypeProperties::HasUnboundGeneric),
1696-
TheDecl(TheDecl), Parent(Parent) { }
1759+
: AnyGenericType(TheDecl, Parent, TypeKind::UnboundGeneric,
1760+
(!Parent || Parent->isCanonical()) ? &C : nullptr,
1761+
properties | RecursiveTypeProperties::HasUnboundGeneric) {}
16971762

16981763
public:
16991764
static UnboundGenericType* get(GenericTypeDecl *TheDecl, Type Parent,
17001765
const ASTContext &C);
17011766

1702-
/// \brief Returns the declaration that declares this type.
1703-
GenericTypeDecl *getDecl() const { return TheDecl; }
1704-
1705-
/// \brief Returns the type of the parent of this type. This will
1706-
/// be null for top-level types or local types, and for non-generic types
1707-
/// will simply be the same as the declared type of the declaration context
1708-
/// of TheDecl. For types nested within generic types, however, this will
1709-
/// involve \c BoundGenericType nodes that provide context for the nested
1710-
/// type, e.g., the bound type Dictionary<String, Int>.Inner would be
1711-
/// represented as an UnboundGenericType with Dictionary<String, Int> as its
1712-
/// parent type.
1713-
Type getParent() const { return Parent; }
1714-
17151767
void Profile(llvm::FoldingSetNodeID &ID) {
17161768
Profile(ID, getDecl(), getParent());
17171769
}
@@ -1723,20 +1775,15 @@ class UnboundGenericType : public TypeBase, public llvm::FoldingSetNode {
17231775
return T->getKind() == TypeKind::UnboundGeneric;
17241776
}
17251777
};
1726-
BEGIN_CAN_TYPE_WRAPPER(UnboundGenericType, Type)
1727-
PROXY_CAN_TYPE_SIMPLE_GETTER(getParent)
1728-
END_CAN_TYPE_WRAPPER(UnboundGenericType, Type)
1778+
DEFINE_EMPTY_CAN_TYPE_WRAPPER(UnboundGenericType, AnyGenericType)
17291779

17301780
inline CanType getAsCanType(const Type &type) { return CanType(type); }
17311781
typedef ArrayRefView<Type,CanType,getAsCanType> CanTypeArrayRef;
17321782

17331783
/// BoundGenericType - An abstract class for applying a generic type to the
17341784
/// given type arguments.
1735-
class BoundGenericType : public TypeBase, public llvm::FoldingSetNode {
1736-
NominalTypeDecl *TheDecl;
1737-
1738-
/// \brief The type of the parent, in which this type is nested.
1739-
Type Parent;
1785+
class BoundGenericType : public NominalOrBoundGenericNominalType,
1786+
public llvm::FoldingSetNode {
17401787

17411788
/// Retrieve the intrusive pointer storage from the subtype
17421789
const Type *getTrailingObjectsPointer() const;
@@ -1754,26 +1801,13 @@ class BoundGenericType : public TypeBase, public llvm::FoldingSetNode {
17541801
static BoundGenericType* get(NominalTypeDecl *TheDecl, Type Parent,
17551802
ArrayRef<Type> GenericArgs);
17561803

1757-
/// \brief Returns the declaration that declares this type.
1758-
NominalTypeDecl *getDecl() const { return TheDecl; }
1759-
1760-
/// \brief Returns the type of the parent of this type. This will
1761-
/// be null for top-level types or local types, and for non-generic types
1762-
/// will simply be the same as the declared type of the declaration context
1763-
/// of TheDecl. For types nested within generic types, however, this will
1764-
/// involve \c BoundGenericType nodes that provide context for the nested
1765-
/// type, e.g., the bound type Dictionary<String, Int>.Inner<Int> would be
1766-
/// represented as a BoundGenericType with Dictionary<String, Int> as its
1767-
/// parent type.
1768-
Type getParent() const { return Parent; }
1769-
17701804
/// Retrieve the set of generic arguments provided at this level.
17711805
ArrayRef<Type> getGenericArgs() const {
17721806
return {getTrailingObjectsPointer(), Bits.BoundGenericType.GenericArgCount};
17731807
}
17741808

17751809
void Profile(llvm::FoldingSetNodeID &ID) {
1776-
Profile(ID, TheDecl, Parent, getGenericArgs());
1810+
Profile(ID, getDecl(), getParent(), getGenericArgs());
17771811
}
17781812
static void Profile(llvm::FoldingSetNodeID &ID, NominalTypeDecl *TheDecl,
17791813
Type Parent, ArrayRef<Type> GenericArgs);
@@ -1784,12 +1818,11 @@ class BoundGenericType : public TypeBase, public llvm::FoldingSetNode {
17841818
T->getKind() <= TypeKind::Last_BoundGenericType;
17851819
}
17861820
};
1787-
BEGIN_CAN_TYPE_WRAPPER(BoundGenericType, Type)
1788-
PROXY_CAN_TYPE_SIMPLE_GETTER(getParent)
1821+
BEGIN_CAN_TYPE_WRAPPER(BoundGenericType, NominalOrBoundGenericNominalType)
17891822
CanTypeArrayRef getGenericArgs() const {
17901823
return CanTypeArrayRef(getPointer()->getGenericArgs());
17911824
}
1792-
END_CAN_TYPE_WRAPPER(BoundGenericType, Type)
1825+
END_CAN_TYPE_WRAPPER(BoundGenericType, NominalOrBoundGenericNominalType)
17931826

17941827

17951828
/// BoundGenericClassType - A subclass of BoundGenericType for the case
@@ -1897,46 +1930,24 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(BoundGenericStructType, BoundGenericType)
18971930
/// NominalType - Represents a type with a name that is significant, such that
18981931
/// the name distinguishes it from other structurally-similar types that have
18991932
/// different names. Nominal types are always canonical.
1900-
class NominalType : public TypeBase {
1901-
/// TheDecl - This is the TypeDecl which declares the given type. It
1902-
/// specifies the name and other useful information about this type.
1903-
NominalTypeDecl * const TheDecl;
1904-
1905-
/// \brief The type of the parent, in which this type is nested.
1906-
Type Parent;
1933+
class NominalType : public NominalOrBoundGenericNominalType {
19071934

19081935
protected:
19091936
NominalType(TypeKind K, const ASTContext *C, NominalTypeDecl *TheDecl,
19101937
Type Parent, RecursiveTypeProperties properties)
1911-
: TypeBase(K, (!Parent || Parent->isCanonical())? C : nullptr,
1912-
properties),
1913-
TheDecl(TheDecl), Parent(Parent) { }
1938+
: NominalOrBoundGenericNominalType(TheDecl, Parent, K,
1939+
(!Parent || Parent->isCanonical())? C : nullptr, properties) {}
19141940

19151941
public:
19161942
static NominalType *get(NominalTypeDecl *D, Type Parent, const ASTContext &C);
19171943

1918-
/// \brief Returns the declaration that declares this type.
1919-
NominalTypeDecl *getDecl() const { return TheDecl; }
1920-
1921-
/// \brief Returns the type of the parent of this type. This will
1922-
/// be null for top-level types or local types, and for non-generic types
1923-
/// will simply be the same as the declared type of the declaration context
1924-
/// of TheDecl. For types nested within generic types, however, this will
1925-
/// involve \c BoundGenericType nodes that provide context for the nested
1926-
/// type, e.g., the type Dictionary<String, Int>.ItemRange would be
1927-
/// represented as a NominalType with Dictionary<String, Int> as its parent
1928-
/// type.
1929-
Type getParent() const { return Parent; }
1930-
19311944
// Implement isa/cast/dyncast/etc.
19321945
static bool classof(const TypeBase *T) {
19331946
return T->getKind() >= TypeKind::First_NominalType &&
19341947
T->getKind() <= TypeKind::Last_NominalType;
19351948
}
19361949
};
1937-
BEGIN_CAN_TYPE_WRAPPER(NominalType, Type)
1938-
PROXY_CAN_TYPE_SIMPLE_GETTER(getParent)
1939-
END_CAN_TYPE_WRAPPER(NominalType, Type)
1950+
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalType, NominalOrBoundGenericNominalType)
19401951

19411952
/// EnumType - This represents the type declared by an EnumDecl.
19421953
class EnumType : public NominalType, public llvm::FoldingSetNode {
@@ -4966,12 +4977,8 @@ inline NominalTypeDecl *TypeBase::getNominalOrBoundGenericNominal() {
49664977
}
49674978

49684979
inline NominalTypeDecl *CanType::getNominalOrBoundGenericNominal() const {
4969-
if (auto nomTy = dyn_cast<NominalType>(*this))
4970-
return nomTy->getDecl();
4971-
4972-
if (auto boundTy = dyn_cast<BoundGenericType>(*this))
4973-
return boundTy->getDecl();
4974-
4980+
if (auto Ty = dyn_cast<NominalOrBoundGenericNominalType>(*this))
4981+
return Ty->getDecl();
49754982
return nullptr;
49764983
}
49774984

@@ -4980,13 +4987,7 @@ inline NominalTypeDecl *TypeBase::getAnyNominal() {
49804987
}
49814988

49824989
inline Type TypeBase::getNominalParent() {
4983-
if (auto classType = getAs<NominalType>()) {
4984-
return classType->getParent();
4985-
} else if (auto unboundType = getAs<UnboundGenericType>()) {
4986-
return unboundType->getParent();
4987-
} else {
4988-
return castTo<BoundGenericType>()->getParent();
4989-
}
4990+
return castTo<AnyGenericType>()->getParent();
49904991
}
49914992

49924993
inline GenericTypeDecl *TypeBase::getAnyGeneric() {
@@ -5055,11 +5056,7 @@ inline CanType CanType::getWithoutSpecifierTypeImpl(CanType type) {
50555056
}
50565057

50575058
inline CanType CanType::getNominalParent() const {
5058-
if (auto classType = dyn_cast<NominalType>(*this)) {
5059-
return classType.getParent();
5060-
} else {
5061-
return cast<BoundGenericType>(*this).getParent();
5062-
}
5059+
return cast<NominalOrBoundGenericNominalType>(*this).getParent();
50635060
}
50645061

50655062
inline Type TupleTypeElt::getVarargBaseTy() const {

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,9 +3243,8 @@ BoundGenericType::BoundGenericType(TypeKind theKind,
32433243
ArrayRef<Type> genericArgs,
32443244
const ASTContext *context,
32453245
RecursiveTypeProperties properties)
3246-
: TypeBase(theKind, context, properties),
3247-
TheDecl(theDecl), Parent(parent)
3248-
{
3246+
: NominalOrBoundGenericNominalType(theDecl, parent, theKind, context,
3247+
properties) {
32493248
Bits.BoundGenericType.GenericArgCount = genericArgs.size();
32503249
// Subtypes are required to provide storage for the generic arguments
32513250
std::uninitialized_copy(genericArgs.begin(), genericArgs.end(),

lib/AST/Type.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,11 @@ NominalTypeDecl *CanType::getAnyNominal() const {
108108
}
109109

110110
GenericTypeDecl *CanType::getAnyGeneric() const {
111-
if (auto nominalTy = dyn_cast<NominalType>(*this))
112-
return (GenericTypeDecl*)nominalTy->getDecl();
113-
114-
if (auto boundTy = dyn_cast<BoundGenericType>(*this))
115-
return (GenericTypeDecl*)boundTy->getDecl();
116-
117-
if (auto unboundTy = dyn_cast<UnboundGenericType>(*this))
118-
return unboundTy->getDecl();
111+
if (auto Ty = dyn_cast<AnyGenericType>(*this))
112+
return Ty->getDecl();
119113
return nullptr;
120114
}
121115

122-
123116
//===----------------------------------------------------------------------===//
124117
// Various Type Methods.
125118
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)