Skip to content

Commit 2eee30d

Browse files
committed
[NFC] Encapsulate the parameter index of an ActorIsolation
1 parent 39e011e commit 2eee30d

File tree

7 files changed

+115
-45
lines changed

7 files changed

+115
-45
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,74 @@ class ActorIsolation {
8888
/// Set to true if this was parsed from SIL.
8989
unsigned silParsed : 1;
9090

91-
unsigned parameterIndex : 27;
91+
/// The opaque value of an EncodedParameterIndex.
92+
/// Only meaningful for ActorInstance.
93+
unsigned encodedParameterIndex : 27;
94+
95+
class EncodedParameterIndex {
96+
enum : unsigned {
97+
SpecialIndex_Capture,
98+
SpecialIndex_Self,
99+
NumSpecialIndexes
100+
};
101+
102+
/// Either a special index or (parameter index + NumSpecialIndexes).
103+
unsigned value;
104+
105+
constexpr EncodedParameterIndex(unsigned value) : value(value) {}
106+
107+
public:
108+
static constexpr EncodedParameterIndex parameter(unsigned index) {
109+
return EncodedParameterIndex(NumSpecialIndexes + index);
110+
}
111+
static constexpr EncodedParameterIndex self() {
112+
return EncodedParameterIndex(SpecialIndex_Self);
113+
}
114+
static constexpr EncodedParameterIndex capture() {
115+
return EncodedParameterIndex(SpecialIndex_Capture);
116+
}
117+
118+
unsigned getParameterIndex() const {
119+
assert(value >= NumSpecialIndexes);
120+
return value - NumSpecialIndexes;
121+
}
122+
bool isSelf() const {
123+
return value == SpecialIndex_Self;
124+
}
125+
bool isCapture() const {
126+
return value == SpecialIndex_Capture;
127+
}
92128

93-
ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex);
129+
static EncodedParameterIndex fromOpaqueValue(unsigned value) {
130+
return EncodedParameterIndex(value);
131+
}
132+
unsigned getOpaqueValue() const {
133+
return value;
134+
}
135+
};
94136

95-
ActorIsolation(Kind kind, VarDecl *actor, unsigned parameterIndex);
137+
ActorIsolation(Kind kind, NominalTypeDecl *actor,
138+
EncodedParameterIndex parameterIndex);
96139

97-
ActorIsolation(Kind kind, Expr *actor, unsigned parameterIndex);
140+
ActorIsolation(Kind kind, VarDecl *actor,
141+
EncodedParameterIndex parameterIndex);
142+
143+
ActorIsolation(Kind kind, Expr *actor,
144+
EncodedParameterIndex parameterIndex);
98145

99146
ActorIsolation(Kind kind, Type globalActor);
100147

148+
EncodedParameterIndex getEncodedParameterIndex() const {
149+
return EncodedParameterIndex::fromOpaqueValue(encodedParameterIndex);
150+
}
151+
101152
public:
102153
// No-argument constructor needed for DenseMap use in PostfixCompletion.cpp
103154
explicit ActorIsolation(Kind kind = Unspecified, bool isSILParsed = false)
104155
: pointer(nullptr), kind(kind), isolatedByPreconcurrency(false),
105-
silParsed(isSILParsed), parameterIndex(0) {}
156+
silParsed(isSILParsed), encodedParameterIndex(0) {
157+
assert(kind != ActorInstance);
158+
}
106159

107160
static ActorIsolation forUnspecified() {
108161
return ActorIsolation(Unspecified);
@@ -125,19 +178,22 @@ class ActorIsolation {
125178

126179
static ActorIsolation forActorInstanceParameter(NominalTypeDecl *actor,
127180
unsigned parameterIndex) {
128-
return ActorIsolation(ActorInstance, actor, parameterIndex + 1);
181+
return ActorIsolation(ActorInstance, actor,
182+
EncodedParameterIndex::parameter(parameterIndex));
129183
}
130184

131185
static ActorIsolation forActorInstanceParameter(VarDecl *actor,
132186
unsigned parameterIndex) {
133-
return ActorIsolation(ActorInstance, actor, parameterIndex + 1);
187+
return ActorIsolation(ActorInstance, actor,
188+
EncodedParameterIndex::parameter(parameterIndex));
134189
}
135190

136191
static ActorIsolation forActorInstanceParameter(Expr *actor,
137192
unsigned parameterIndex);
138193

139194
static ActorIsolation forActorInstanceCapture(VarDecl *capturedActor) {
140-
return ActorIsolation(ActorInstance, capturedActor, 0);
195+
return ActorIsolation(ActorInstance, capturedActor,
196+
EncodedParameterIndex::capture());
141197
}
142198

143199
static ActorIsolation forGlobalActor(Type globalActor) {
@@ -187,17 +243,22 @@ class ActorIsolation {
187243
bool isNonisolatedUnsafe() const { return kind == NonisolatedUnsafe; }
188244

189245
/// Retrieve the parameter to which actor-instance isolation applies.
190-
///
191-
/// Parameter 0 is `self`.
192-
unsigned getActorInstanceParameter() const {
246+
unsigned getActorInstanceParameterIndex() const {
193247
assert(getKind() == ActorInstance);
194-
return parameterIndex;
248+
return getEncodedParameterIndex().getParameterIndex();
249+
}
250+
251+
/// Given that this is actor instance isolation, is it a capture?
252+
bool isActorInstanceForCapture() const {
253+
assert(getKind() == ActorInstance);
254+
return getEncodedParameterIndex().isCapture();
195255
}
196256

197257
/// Returns true if this is an actor-instance isolation that additionally
198258
/// applies to the self parameter of a method.
199259
bool isActorInstanceForSelfParameter() const {
200-
return getActorInstanceParameter() == 0;
260+
assert(getKind() == ActorInstance);
261+
return getEncodedParameterIndex().isSelf();
201262
}
202263

203264
bool isSILParsed() const { return silParsed; }
@@ -285,13 +346,13 @@ class ActorIsolation {
285346
id.AddPointer(pointer);
286347
id.AddBoolean(isolatedByPreconcurrency);
287348
id.AddBoolean(silParsed);
288-
id.AddInteger(parameterIndex);
349+
id.AddInteger(encodedParameterIndex);
289350
}
290351

291352
friend llvm::hash_code hash_value(const ActorIsolation &state) {
292353
return llvm::hash_combine(state.kind, state.pointer,
293354
state.isolatedByPreconcurrency, state.silParsed,
294-
state.parameterIndex);
355+
state.encodedParameterIndex);
295356
}
296357

297358
void print(llvm::raw_ostream &os) const;

lib/AST/ActorIsolation.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,27 @@ ActorIsolation ActorIsolation::forMainActor(ASTContext &ctx) {
2323
ctx.getMainActorType()->mapTypeOutOfContext());
2424
}
2525

26+
// These constructors are defined out-of-line so that including ActorIsolation.h
27+
// doesn't require a bunch of other headers to be included.
28+
2629
ActorIsolation::ActorIsolation(Kind kind, NominalTypeDecl *actor,
27-
unsigned parameterIndex)
30+
EncodedParameterIndex parameterIndex)
2831
: actorInstance(actor), kind(kind), isolatedByPreconcurrency(false),
29-
silParsed(false), parameterIndex(parameterIndex) {}
32+
silParsed(false), encodedParameterIndex(parameterIndex.getOpaqueValue()) {}
3033

3134
ActorIsolation::ActorIsolation(Kind kind, VarDecl *actor,
32-
unsigned parameterIndex)
35+
EncodedParameterIndex parameterIndex)
3336
: actorInstance(actor), kind(kind), isolatedByPreconcurrency(false),
34-
silParsed(false), parameterIndex(parameterIndex) {}
37+
silParsed(false), encodedParameterIndex(parameterIndex.getOpaqueValue()) {}
3538

36-
ActorIsolation::ActorIsolation(Kind kind, Expr *actor, unsigned parameterIndex)
39+
ActorIsolation::ActorIsolation(Kind kind, Expr *actor,
40+
EncodedParameterIndex parameterIndex)
3741
: actorInstance(actor), kind(kind), isolatedByPreconcurrency(false),
38-
silParsed(false), parameterIndex(parameterIndex) {}
42+
silParsed(false), encodedParameterIndex(parameterIndex.getOpaqueValue()) {}
3943

4044
ActorIsolation::ActorIsolation(Kind kind, Type globalActor)
4145
: globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false),
42-
silParsed(false), parameterIndex(0) {}
46+
silParsed(false), encodedParameterIndex(0) {}
4347

4448
ActorIsolation
4549
ActorIsolation::forActorInstanceParameter(Expr *actor,
@@ -67,25 +71,29 @@ ActorIsolation::forActorInstanceParameter(Expr *actor,
6771
}
6872
}
6973

70-
return ActorIsolation(ActorInstance, actor, parameterIndex + 1);
74+
return ActorIsolation(ActorInstance, actor,
75+
EncodedParameterIndex::parameter(parameterIndex));
7176
}
7277

7378
ActorIsolation ActorIsolation::forActorInstanceSelf(ValueDecl *decl) {
7479
if (auto *fn = dyn_cast<AbstractFunctionDecl>(decl))
75-
return ActorIsolation(ActorInstance, fn->getImplicitSelfDecl(), 0);
80+
return ActorIsolation(ActorInstance, fn->getImplicitSelfDecl(),
81+
EncodedParameterIndex::self());
7682

7783
if (auto *storage = dyn_cast<AbstractStorageDecl>(decl)) {
7884
if (auto *fn = storage->getAccessor(AccessorKind::Get)) {
79-
return ActorIsolation(ActorInstance, fn->getImplicitSelfDecl(), 0);
85+
return ActorIsolation(ActorInstance, fn->getImplicitSelfDecl(),
86+
EncodedParameterIndex::self());
8087
}
8188
}
8289

8390
auto *dc = decl->getDeclContext();
84-
return ActorIsolation(ActorInstance, dc->getSelfNominalTypeDecl(), 0);
91+
return ActorIsolation(ActorInstance, dc->getSelfNominalTypeDecl(),
92+
EncodedParameterIndex::self());
8593
}
8694

8795
ActorIsolation ActorIsolation::forActorInstanceSelf(NominalTypeDecl *selfDecl) {
88-
return ActorIsolation(ActorInstance, selfDecl, 0);
96+
return ActorIsolation(ActorInstance, selfDecl, EncodedParameterIndex::self());
8997
}
9098

9199
NominalTypeDecl *ActorIsolation::getActor() const {

lib/SILGen/SILGenApply.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6122,13 +6122,15 @@ RValue SILGenFunction::emitApply(
61226122
SILValue executor;
61236123
switch (*implicitActorHopTarget) {
61246124
case ActorIsolation::ActorInstance:
6125-
if (unsigned paramIndex =
6126-
implicitActorHopTarget->getActorInstanceParameter()) {
6125+
assert(!implicitActorHopTarget->isActorInstanceForCapture());
6126+
if (implicitActorHopTarget->isActorInstanceForSelfParameter()) {
6127+
executor = emitLoadActorExecutor(loc, args.back());
6128+
} else {
6129+
unsigned paramIndex =
6130+
implicitActorHopTarget->getActorInstanceParameterIndex();
61276131
auto isolatedIndex = calleeTypeInfo.origFormalType
6128-
->getLoweredParamIndex(paramIndex - 1);
6132+
->getLoweredParamIndex(paramIndex);
61296133
executor = emitLoadActorExecutor(loc, args[isolatedIndex]);
6130-
} else {
6131-
executor = emitLoadActorExecutor(loc, args.back());
61326134
}
61336135
break;
61346136

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -651,9 +651,7 @@ SILGenFunction::emitClosureIsolation(SILLocation loc, SILDeclRef constant,
651651
isolation.getGlobalActor()->getCanonicalType());
652652

653653
case ActorIsolation::ActorInstance: {
654-
// This should always be a capture. That's not expressed super-cleanly
655-
// in ActorIsolation, unfortunately.
656-
assert(isolation.getActorInstanceParameter() == 0);
654+
assert(isolation.isActorInstanceForCapture());
657655
auto capture = isolation.getActorInstance();
658656
assert(capture);
659657
return emitLoadOfCaptureIsolation(*this, loc, capture, constant, captures);

lib/SILGen/SILGenConstructor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ static bool ctorHopsInjectedByDefiniteInit(ConstructorDecl *ctor,
595595
// must be self-isolated
596596
switch (isolation) {
597597
case ActorIsolation::ActorInstance:
598-
return isolation.getActorInstanceParameter() == 0;
598+
return isolation.isActorInstanceForSelfParameter();
599599

600600
case ActorIsolation::Erased:
601601
llvm_unreachable("constructor cannot have erased isolation");

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7409,7 +7409,7 @@ void SILGenFunction::emitProtocolWitness(
74097409

74107410
// For an instance actor, get the actor 'self'.
74117411
if (*enterIsolation == ActorIsolation::ActorInstance) {
7412-
assert(enterIsolation->getActorInstanceParameter() == 0 && "Not self?");
7412+
assert(enterIsolation->isActorInstanceForSelfParameter() && "Not self?");
74137413
auto actorSelfVal = origParams.back();
74147414

74157415
if (actorSelfVal.getType().isAddress()) {

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,12 +3549,14 @@ namespace {
35493549
if (isolation == ActorIsolation::ActorInstance) {
35503550
VarDecl *var = isolation.getActorInstance();
35513551
if (!var) {
3552+
assert(!isolation.isActorInstanceForCapture() &&
3553+
"capture isolation without a variable reference?");
35523554
auto dc = const_cast<DeclContext *>(getDeclContext());
3553-
auto paramIdx = isolation.getActorInstanceParameter();
3554-
if (paramIdx == 0) {
3555+
if (isolation.isActorInstanceForSelfParameter()) {
35553556
var = cast<AbstractFunctionDecl>(dc)->getImplicitSelfDecl();
35563557
} else {
3557-
var = const_cast<ParamDecl *>(getParameterAt(dc, paramIdx - 1));
3558+
auto paramIdx = isolation.getActorInstanceParameterIndex();
3559+
var = const_cast<ParamDecl *>(getParameterAt(dc, paramIdx));
35583560
}
35593561
}
35603562
return var;
@@ -4326,11 +4328,10 @@ namespace {
43264328
const VarDecl *var = isolation.getActorInstance();
43274329
if (!var) {
43284330
auto dc = getDeclContext();
4329-
auto paramIdx = isolation.getActorInstanceParameter();
4330-
if (paramIdx == 0) {
4331+
if (isolation.isActorInstanceForSelfParameter()) {
43314332
var = cast<AbstractFunctionDecl>(dc)->getImplicitSelfDecl();
43324333
} else {
4333-
var = getParameterAt(dc, paramIdx - 1);
4334+
var = getParameterAt(dc, isolation.getActorInstanceParameterIndex());
43344335
}
43354336
}
43364337
actorExpr = new (ctx) DeclRefExpr(
@@ -4640,7 +4641,7 @@ namespace {
46404641
if (!partialApply &&
46414642
(result.isolation.isGlobalActor() ||
46424643
(result.isolation == ActorIsolation::ActorInstance &&
4643-
result.isolation.getActorInstanceParameter() > 0)) &&
4644+
!result.isolation.isActorInstanceForSelfParameter())) &&
46444645
isa<AbstractFunctionDecl>(decl))
46454646
return false;
46464647

@@ -8022,7 +8023,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
80228023
// The declaration we are accessing is actor-isolated. First, check whether
80238024
// we are on the same actor already.
80248025
if (actorInstance && declIsolation == ActorIsolation::ActorInstance &&
8025-
declIsolation.getActorInstanceParameter() == 0) {
8026+
declIsolation.isActorInstanceForSelfParameter()) {
80268027
// If this instance is isolated, we're in the same concurrency domain.
80278028
if (actorInstance->isIsolated())
80288029
return forSameConcurrencyDomain(declIsolation, options);

0 commit comments

Comments
 (0)