Skip to content

Commit 89b6993

Browse files
committed
[AST] Convert NormalProtocolConformance to use bitfields for its aux information (state, flags etc.)
1 parent 4bef068 commit 89b6993

File tree

3 files changed

+81
-68
lines changed

3 files changed

+81
-68
lines changed

include/swift/AST/DeclContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ enum class ConformanceEntryKind : unsigned {
162162

163163
/// Implied by an explicitly-specified conformance.
164164
Implied,
165+
166+
Last_Kind = Implied
165167
};
166168

167169
/// Describes the kind of conformance lookup desired.

include/swift/AST/ProtocolConformance.h

Lines changed: 79 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/Witness.h"
2525
#include "swift/Basic/Compiler.h"
2626
#include "swift/Basic/Debug.h"
27+
#include "swift/Basic/InlineBitfield.h"
2728
#include "llvm/ADT/ArrayRef.h"
2829
#include "llvm/ADT/DenseMap.h"
2930
#include "llvm/ADT/FoldingSet.h"
@@ -55,10 +56,10 @@ typedef llvm::DenseMap<AssociatedTypeDecl *, TypeWitnessAndDecl>
5556

5657
/// Describes the kind of protocol conformance structure used to encode
5758
/// conformance.
58-
enum class ProtocolConformanceKind {
59+
enum class ProtocolConformanceKind : unsigned {
5960
/// "Normal" conformance of a (possibly generic) nominal type, which
6061
/// contains complete mappings.
61-
Normal = 0,
62+
Normal,
6263
/// Self-conformance of a protocol to itself.
6364
Self,
6465
/// Conformance for a specialization of a generic type, which projects the
@@ -82,13 +83,25 @@ enum : unsigned {
8283
/// incomplete, or currently being checked.
8384
enum class ProtocolConformanceState {
8485
/// The conformance has been fully checked.
85-
Complete,
86+
Complete = 0,
8687
/// The conformance is known but is not yet complete.
8788
Incomplete,
8889
/// The conformance's type witnesses are currently being resolved.
8990
CheckingTypeWitnesses,
9091
/// The conformance is being checked.
9192
Checking,
93+
94+
Last_State = Checking
95+
};
96+
97+
enum : unsigned {
98+
NumProtocolConformanceStateBits =
99+
countBitsUsed(static_cast<unsigned>(ProtocolConformanceState::Last_State))
100+
};
101+
102+
enum : unsigned {
103+
NumConformanceEntryKindBits =
104+
countBitsUsed(static_cast<unsigned>(ConformanceEntryKind::Last_Kind))
92105
};
93106

94107
/// Describes how a particular type conforms to a given protocol,
@@ -115,6 +128,38 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance
115128
/// The kind of protocol conformance.
116129
Kind : bitmax(NumProtocolConformanceKindBits, 8)
117130
);
131+
132+
SWIFT_INLINE_BITFIELD_EMPTY(RootProtocolConformance, ProtocolConformance);
133+
134+
SWIFT_INLINE_BITFIELD_FULL(NormalProtocolConformance, RootProtocolConformance,
135+
1+1+1+1+bitmax(NumProtocolConformanceStateBits,8)+
136+
bitmax(NumConformanceEntryKindBits,8),
137+
/// Indicates whether the conformance is invalid.
138+
IsInvalid : 1,
139+
/// The conformance was labeled with @unchecked.
140+
IsUnchecked : 1,
141+
/// The conformance was labeled with @preconcurrency.
142+
IsPreconcurrency : 1,
143+
/// We have allocated the AssociatedConformances array (but not necessarily
144+
/// populated any of its elements).
145+
HasComputedAssociatedConformances : 1,
146+
147+
: NumPadBits,
148+
149+
/// The current state of the conformance.
150+
State : bitmax(NumProtocolConformanceStateBits, 8),
151+
/// The reason that this conformance exists.
152+
///
153+
/// Either Explicit (e.g. 'struct Foo: Protocol {}' or 'extension Foo:
154+
/// Protocol {}'), Synthesized (e.g. RawRepresentable for 'enum Foo: Int {}')
155+
/// or Implied (e.g. 'Foo : Protocol' in 'protocol Other: Protocol {} struct
156+
/// Foo: Other {}'). In only the latter case, the conformance is non-null and
157+
/// points to the conformance that implies this one.
158+
///
159+
/// This should never be Inherited: that is handled by
160+
/// InheritedProtocolConformance.
161+
SourceKind : bitmax(NumConformanceEntryKindBits, 8)
162+
);
118163
} Bits;
119164
// clang-format on
120165

@@ -456,49 +501,17 @@ class NormalProtocolConformance : public RootProtocolConformance,
456501
friend class ValueWitnessRequest;
457502
friend class TypeWitnessRequest;
458503

459-
/// The protocol being conformed to and its current state.
460-
llvm::PointerIntPair<ProtocolDecl *, 2, ProtocolConformanceState>
461-
ProtocolAndState;
504+
/// The protocol being conformed to.
505+
ProtocolDecl *Protocol;
462506

463507
/// The location of this protocol conformance in the source.
464508
SourceLoc Loc;
465509

466-
// Flag bits used in ContextAndBits.
467-
enum {
468-
/// The conformance was labeled with @unchecked.
469-
UncheckedFlag = 0x01,
470-
471-
/// The conformance was labeled with @preconcurrency.
472-
PreconcurrencyFlag = 0x02,
473-
474-
/// We have allocated the AssociatedConformances array (but not necessarily
475-
/// populated any of its elements).
476-
HasComputedAssociatedConformancesFlag = 0x04,
477-
};
478-
479510
/// The declaration context containing the ExtensionDecl or
480511
/// NominalTypeDecl that declared the conformance.
481-
///
482-
/// Also stores the "unchecked", "preconcurrency" and "has computed associated
483-
/// conformances" bits.
484-
llvm::PointerIntPair<DeclContext *, 3, unsigned> ContextAndBits;
485-
486-
/// Indicates whether the conformance is invalid.
487-
bool Invalid : 1;
512+
DeclContext *Context;
488513

489-
/// The reason that this conformance exists.
490-
///
491-
/// Either Explicit (e.g. 'struct Foo: Protocol {}' or 'extension Foo:
492-
/// Protocol {}'), Synthesized (e.g. RawRepresentable for 'enum Foo: Int {}')
493-
/// or Implied (e.g. 'Foo : Protocol' in 'protocol Other: Protocol {} struct
494-
/// Foo: Other {}'). In only the latter case, the conformance is non-null and
495-
/// points to the conformance that implies this one.
496-
///
497-
/// This should never be Inherited: that is handled by
498-
/// InheritedProtocolConformance.
499-
llvm::PointerIntPair<NormalProtocolConformance *, 3, ConformanceEntryKind>
500-
SourceKindAndImplyingConformance = {nullptr,
501-
ConformanceEntryKind::Explicit};
514+
NormalProtocolConformance *ImplyingConformance = nullptr;
502515

503516
/// The mapping of individual requirements in the protocol over to
504517
/// the declarations that satisfy those requirements.
@@ -529,25 +542,27 @@ class NormalProtocolConformance : public RootProtocolConformance,
529542
bool isPreconcurrency)
530543
: RootProtocolConformance(ProtocolConformanceKind::Normal,
531544
conformingType),
532-
ProtocolAndState(protocol, state), Loc(loc),
533-
ContextAndBits(dc, ((isUnchecked ? UncheckedFlag : 0) |
534-
(isPreconcurrency ? PreconcurrencyFlag : 0))),
535-
Invalid(false) {
545+
Protocol(protocol), Loc(loc), Context(dc) {
536546
assert(!conformingType->hasArchetype() &&
537547
"ProtocolConformances should store interface types");
548+
setState(state);
549+
Bits.NormalProtocolConformance.IsInvalid = false;
550+
Bits.NormalProtocolConformance.IsUnchecked = isUnchecked;
551+
Bits.NormalProtocolConformance.IsPreconcurrency = isPreconcurrency;
552+
Bits.NormalProtocolConformance.HasComputedAssociatedConformances = false;
553+
Bits.NormalProtocolConformance.SourceKind =
554+
unsigned(ConformanceEntryKind::Explicit);
538555
}
539556

540557
/// Get the protocol being conformed to.
541-
ProtocolDecl *getProtocol() const { return ProtocolAndState.getPointer(); }
558+
ProtocolDecl *getProtocol() const { return Protocol; }
542559

543560
/// Retrieve the location of this
544561
SourceLoc getLoc() const { return Loc; }
545562

546563
/// Get the declaration context that contains the conforming extension or
547564
/// nominal type declaration.
548-
DeclContext *getDeclContext() const {
549-
return ContextAndBits.getPointer();
550-
}
565+
DeclContext *getDeclContext() const { return Context; }
551566

552567
/// Get any additional requirements that are required for this conformance to
553568
/// be satisfied, e.g. for Array<T>: Equatable, T: Equatable also needs
@@ -559,59 +574,59 @@ class NormalProtocolConformance : public RootProtocolConformance,
559574

560575
/// Retrieve the state of this conformance.
561576
ProtocolConformanceState getState() const {
562-
return ProtocolAndState.getInt();
577+
return static_cast<ProtocolConformanceState>(
578+
Bits.NormalProtocolConformance.State);
563579
}
564580

565581
/// Set the state of this conformance.
566582
void setState(ProtocolConformanceState state) {
567-
ProtocolAndState.setInt(state);
583+
Bits.NormalProtocolConformance.State = unsigned(state);
568584
}
569585

570586
/// Determine whether this conformance is invalid.
571-
bool isInvalid() const {
572-
return Invalid;
573-
}
587+
bool isInvalid() const { return Bits.NormalProtocolConformance.IsInvalid; }
574588

575589
/// Mark this conformance as invalid.
576-
void setInvalid() {
577-
Invalid = true;
578-
}
590+
void setInvalid() { Bits.NormalProtocolConformance.IsInvalid = true; }
579591

580592
/// Whether this is an "unchecked" conformance.
581593
bool isUnchecked() const {
582-
return ContextAndBits.getInt() & UncheckedFlag;
594+
return Bits.NormalProtocolConformance.IsUnchecked;
583595
}
584596

585597
/// Mark the conformance as unchecked (equivalent to the @unchecked
586598
/// conformance attribute).
587599
void setUnchecked() {
588600
// OK to mutate because the flags are not part of the folding set node ID.
589-
ContextAndBits.setInt(ContextAndBits.getInt() | UncheckedFlag);
601+
Bits.NormalProtocolConformance.IsUnchecked = true;
590602
}
591603

592604
/// Whether this is an preconcurrency conformance.
593-
bool isPreconcurrency() const;
605+
bool isPreconcurrency() const {
606+
return Bits.NormalProtocolConformance.IsPreconcurrency;
607+
}
594608

595609
/// Determine whether we've lazily computed the associated conformance array
596610
/// already.
597611
bool hasComputedAssociatedConformances() const {
598-
return ContextAndBits.getInt() & HasComputedAssociatedConformancesFlag;
612+
return Bits.NormalProtocolConformance.HasComputedAssociatedConformances;
599613
}
600614

601615
/// Mark this conformance as having computed the assocaited conformance array.
602616
void setHasComputedAssociatedConformances() {
603-
ContextAndBits.setInt(ContextAndBits.getInt() | HasComputedAssociatedConformancesFlag);
617+
Bits.NormalProtocolConformance.HasComputedAssociatedConformances = true;
604618
}
605619

606620
/// Get the kind of source from which this conformance comes.
607621
ConformanceEntryKind getSourceKind() const {
608-
return SourceKindAndImplyingConformance.getInt();
622+
return static_cast<ConformanceEntryKind>(
623+
Bits.NormalProtocolConformance.SourceKind);
609624
}
610625

611626
/// Get the protocol conformance which implied this implied conformance.
612627
NormalProtocolConformance *getImplyingConformance() const {
613628
assert(getSourceKind() == ConformanceEntryKind::Implied);
614-
return SourceKindAndImplyingConformance.getPointer();
629+
return ImplyingConformance;
615630
}
616631

617632
void setSourceKindAndImplyingConformance(
@@ -624,7 +639,8 @@ class NormalProtocolConformance : public RootProtocolConformance,
624639
"an implied conformance needs something that implies it");
625640
assert(sourceKind != ConformanceEntryKind::PreMacroExpansion &&
626641
"cannot create conformance pre-macro-expansion");
627-
SourceKindAndImplyingConformance = {implyingConformance, sourceKind};
642+
Bits.NormalProtocolConformance.SourceKind = unsigned(sourceKind);
643+
ImplyingConformance = implyingConformance;
628644
}
629645

630646
/// Determine whether this conformance is lazily loaded.

lib/AST/ProtocolConformance.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,6 @@ bool NormalProtocolConformance::isResilient() const {
338338
return getDeclContext()->getParentModule()->isResilient();
339339
}
340340

341-
bool NormalProtocolConformance::isPreconcurrency() const {
342-
// The conformance is explicitly marked as `@preconcurrency`.
343-
return ContextAndBits.getInt() & PreconcurrencyFlag;
344-
}
345-
346341
llvm::Optional<ArrayRef<Requirement>>
347342
ProtocolConformance::getConditionalRequirementsIfAvailable() const {
348343
CONFORMANCE_SUBCLASS_DISPATCH(getConditionalRequirementsIfAvailable, ());

0 commit comments

Comments
 (0)