Skip to content

Commit 00463df

Browse files
committed
[NFC] Encapsulate the parameter index of an ActorIsolation
1 parent f5f058f commit 00463df

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
@@ -6123,13 +6123,15 @@ RValue SILGenFunction::emitApply(
61236123
SILValue executor;
61246124
switch (*implicitActorHopTarget) {
61256125
case ActorIsolation::ActorInstance:
6126-
if (unsigned paramIndex =
6127-
implicitActorHopTarget->getActorInstanceParameter()) {
6126+
assert(!implicitActorHopTarget->isActorInstanceForCapture());
6127+
if (implicitActorHopTarget->isActorInstanceForSelfParameter()) {
6128+
executor = emitLoadActorExecutor(loc, args.back());
6129+
} else {
6130+
unsigned paramIndex =
6131+
implicitActorHopTarget->getActorInstanceParameterIndex();
61286132
auto isolatedIndex = calleeTypeInfo.origFormalType
6129-
->getLoweredParamIndex(paramIndex - 1);
6133+
->getLoweredParamIndex(paramIndex);
61306134
executor = emitLoadActorExecutor(loc, args[isolatedIndex]);
6131-
} else {
6132-
executor = emitLoadActorExecutor(loc, args.back());
61336135
}
61346136
break;
61356137

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
@@ -7402,7 +7402,7 @@ void SILGenFunction::emitProtocolWitness(
74027402

74037403
// For an instance actor, get the actor 'self'.
74047404
if (*enterIsolation == ActorIsolation::ActorInstance) {
7405-
assert(enterIsolation->getActorInstanceParameter() == 0 && "Not self?");
7405+
assert(enterIsolation->isActorInstanceForSelfParameter() && "Not self?");
74067406
auto actorSelfVal = origParams.back();
74077407

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

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3565,12 +3565,14 @@ namespace {
35653565
if (isolation == ActorIsolation::ActorInstance) {
35663566
VarDecl *var = isolation.getActorInstance();
35673567
if (!var) {
3568+
assert(!isolation.isActorInstanceForCapture() &&
3569+
"capture isolation without a variable reference?");
35683570
auto dc = const_cast<DeclContext *>(getDeclContext());
3569-
auto paramIdx = isolation.getActorInstanceParameter();
3570-
if (paramIdx == 0) {
3571+
if (isolation.isActorInstanceForSelfParameter()) {
35713572
var = cast<AbstractFunctionDecl>(dc)->getImplicitSelfDecl();
35723573
} else {
3573-
var = const_cast<ParamDecl *>(getParameterAt(dc, paramIdx - 1));
3574+
auto paramIdx = isolation.getActorInstanceParameterIndex();
3575+
var = const_cast<ParamDecl *>(getParameterAt(dc, paramIdx));
35743576
}
35753577
}
35763578
return var;
@@ -4342,11 +4344,10 @@ namespace {
43424344
const VarDecl *var = isolation.getActorInstance();
43434345
if (!var) {
43444346
auto dc = getDeclContext();
4345-
auto paramIdx = isolation.getActorInstanceParameter();
4346-
if (paramIdx == 0) {
4347+
if (isolation.isActorInstanceForSelfParameter()) {
43474348
var = cast<AbstractFunctionDecl>(dc)->getImplicitSelfDecl();
43484349
} else {
4349-
var = getParameterAt(dc, paramIdx - 1);
4350+
var = getParameterAt(dc, isolation.getActorInstanceParameterIndex());
43504351
}
43514352
}
43524353
actorExpr = new (ctx) DeclRefExpr(
@@ -4656,7 +4657,7 @@ namespace {
46564657
if (!partialApply &&
46574658
(result.isolation.isGlobalActor() ||
46584659
(result.isolation == ActorIsolation::ActorInstance &&
4659-
result.isolation.getActorInstanceParameter() > 0)) &&
4660+
!result.isolation.isActorInstanceForSelfParameter())) &&
46604661
isa<AbstractFunctionDecl>(decl))
46614662
return false;
46624663

@@ -8107,7 +8108,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
81078108
// The declaration we are accessing is actor-isolated. First, check whether
81088109
// we are on the same actor already.
81098110
if (actorInstance && declIsolation == ActorIsolation::ActorInstance &&
8110-
declIsolation.getActorInstanceParameter() == 0) {
8111+
declIsolation.isActorInstanceForSelfParameter()) {
81118112
// If this instance is isolated, we're in the same concurrency domain.
81128113
if (actorInstance->isIsolated())
81138114
return forSameConcurrencyDomain(declIsolation, options);

0 commit comments

Comments
 (0)