Skip to content

Commit a95a4b9

Browse files
authored
Merge pull request #16553 from davezarzycki/nfc_better_cantype_perf
NFC: better CanType perf
2 parents a45928c + b6014e8 commit a95a4b9

File tree

2 files changed

+32
-24
lines changed

2 files changed

+32
-24
lines changed

include/swift/AST/Types.h

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,14 @@ class alignas(1 << TypeAlignInBits) TypeBase {
255255
TypeBase(const TypeBase&) = delete;
256256
void operator=(const TypeBase&) = delete;
257257

258-
/// CanonicalType - This field is always set to the ASTContext for canonical
259-
/// types, and is otherwise lazily populated by ASTContext when the canonical
260-
/// form of a non-canonical type is requested.
261-
llvm::PointerUnion<TypeBase *, const ASTContext *> CanonicalType;
258+
/// This union contains to the ASTContext for canonical types, and is
259+
/// otherwise lazily populated by ASTContext when the canonical form of a
260+
/// non-canonical type is requested. The disposition of the union is stored
261+
/// outside of the union for performance. See Bits.TypeBase.IsCanonical.
262+
union {
263+
CanType CanonicalType;
264+
const ASTContext *Context;
265+
};
262266

263267
/// Returns true if the given type is a sugared type.
264268
///
@@ -275,11 +279,14 @@ class alignas(1 << TypeAlignInBits) TypeBase {
275279
union { uint64_t OpaqueBits;
276280

277281
SWIFT_INLINE_BITFIELD_BASE(TypeBase, bitmax(NumTypeKindBits,8) +
278-
RecursiveTypeProperties::BitWidth,
282+
RecursiveTypeProperties::BitWidth + 1,
279283
/// Kind - The discriminator that indicates what subclass of type this is.
280284
Kind : bitmax(NumTypeKindBits,8),
281285

282-
Properties : RecursiveTypeProperties::BitWidth
286+
Properties : RecursiveTypeProperties::BitWidth,
287+
288+
/// Whether this type is canonical or not.
289+
IsCanonical : 1
283290
);
284291

285292
SWIFT_INLINE_BITFIELD(ErrorType, TypeBase, 1,
@@ -384,12 +391,15 @@ class alignas(1 << TypeAlignInBits) TypeBase {
384391
protected:
385392
TypeBase(TypeKind kind, const ASTContext *CanTypeCtx,
386393
RecursiveTypeProperties properties)
387-
: CanonicalType((TypeBase*)nullptr) {
394+
: Context(nullptr) {
388395
Bits.OpaqueBits = 0;
389396
Bits.TypeBase.Kind = static_cast<unsigned>(kind);
397+
Bits.TypeBase.IsCanonical = false;
390398
// If this type is canonical, switch the CanonicalType union to ASTContext.
391-
if (CanTypeCtx)
392-
CanonicalType = CanTypeCtx;
399+
if (CanTypeCtx) {
400+
Bits.TypeBase.IsCanonical = true;
401+
Context = CanTypeCtx;
402+
}
393403
setRecursiveProperties(properties);
394404
}
395405

@@ -403,7 +413,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
403413
TypeKind getKind() const { return static_cast<TypeKind>(Bits.TypeBase.Kind); }
404414

405415
/// isCanonical - Return true if this is a canonical type.
406-
bool isCanonical() const { return CanonicalType.is<const ASTContext *>(); }
416+
bool isCanonical() const { return Bits.TypeBase.IsCanonical; }
407417

408418
/// hasCanonicalTypeComputed - Return true if we've already computed a
409419
/// canonical version of this type.
@@ -419,7 +429,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
419429
if (isCanonical())
420430
return CanType(const_cast<TypeBase*>(this));
421431
if (hasCanonicalTypeComputed())
422-
return CanType(CanonicalType.get<TypeBase*>());
432+
return CanonicalType;
423433
return const_cast<TypeBase*>(this)->computeCanonicalType();
424434
}
425435

@@ -434,11 +444,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
434444
/// getASTContext - Return the ASTContext that this type belongs to.
435445
ASTContext &getASTContext() {
436446
// If this type is canonical, it has the ASTContext in it.
437-
if (CanonicalType.is<const ASTContext *>())
438-
return const_cast<ASTContext&>(*CanonicalType.get<const ASTContext *>());
447+
if (isCanonical())
448+
return *const_cast<ASTContext*>(Context);
439449
// If not, canonicalize it to get the Context.
440-
return const_cast<ASTContext&>(*getCanonicalType()->
441-
CanonicalType.get<const ASTContext *>());
450+
return *const_cast<ASTContext*>(getCanonicalType()->Context);
442451
}
443452

444453
/// isEqual - Return true if these two types are equal, ignoring sugar.
@@ -5262,7 +5271,13 @@ inline CanType CanType::getWithoutSpecifierTypeImpl(CanType type) {
52625271
inline CanType CanType::getNominalParent() const {
52635272
return cast<NominalOrBoundGenericNominalType>(*this).getParent();
52645273
}
5265-
5274+
5275+
inline bool CanType::isActuallyCanonicalOrNull() const {
5276+
return getPointer() == nullptr ||
5277+
getPointer() == llvm::DenseMapInfo<TypeBase *>::getTombstoneKey() ||
5278+
getPointer()->isCanonical();
5279+
}
5280+
52665281
inline Type TupleTypeElt::getVarargBaseTy() const {
52675282
TypeBase *T = getType().getPointer();
52685283
if (auto *AT = dyn_cast<ArraySliceType>(T))

lib/AST/Type.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,6 @@ void *TypeBase::operator new(size_t bytes, const ASTContext &ctx,
102102
return ctx.Allocate(bytes, alignment, arena);
103103
}
104104

105-
bool CanType::isActuallyCanonicalOrNull() const {
106-
return getPointer() == nullptr ||
107-
getPointer() == llvm::DenseMapInfo<TypeBase *>::getTombstoneKey() ||
108-
getPointer()->isCanonical();
109-
}
110-
111105
NominalTypeDecl *CanType::getAnyNominal() const {
112106
return dyn_cast_or_null<NominalTypeDecl>(getAnyGeneric());
113107
}
@@ -1249,8 +1243,7 @@ CanType TypeBase::computeCanonicalType() {
12491243

12501244
// Cache the canonical type for future queries.
12511245
assert(Result && "Case not implemented!");
1252-
CanonicalType = Result;
1253-
return CanType(Result);
1246+
return CanonicalType = CanType(Result);
12541247
}
12551248

12561249
CanType TypeBase::getCanonicalType(GenericSignature *sig) {

0 commit comments

Comments
 (0)