Skip to content

Commit 0db7246

Browse files
authored
Merge pull request #60799 from DougGregor/generalize-actor-isolation
2 parents 18b2225 + 5191c31 commit 0db7246

File tree

10 files changed

+140
-156
lines changed

10 files changed

+140
-156
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,17 @@ class ActorIsolation {
7474
Type globalActor;
7575
void *pointer;
7676
};
77-
uint8_t kind : 3;
78-
uint8_t isolatedByPreconcurrency : 1;
77+
unsigned kind : 3;
78+
unsigned isolatedByPreconcurrency : 1;
79+
unsigned parameterIndex : 28;
7980

80-
ActorIsolation(Kind kind, NominalTypeDecl *actor)
81-
: actor(actor), kind(kind), isolatedByPreconcurrency(false) { }
81+
ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex)
82+
: actor(actor), kind(kind), isolatedByPreconcurrency(false),
83+
parameterIndex(parameterIndex) { }
8284

8385
ActorIsolation(Kind kind, Type globalActor)
84-
: globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false) { }
86+
: globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false),
87+
parameterIndex(0) { }
8588

8689
public:
8790
static ActorIsolation forUnspecified() {
@@ -92,8 +95,13 @@ class ActorIsolation {
9295
return ActorIsolation(Independent, nullptr);
9396
}
9497

95-
static ActorIsolation forActorInstance(NominalTypeDecl *actor) {
96-
return ActorIsolation(ActorInstance, actor);
98+
static ActorIsolation forActorInstanceSelf(NominalTypeDecl *actor) {
99+
return ActorIsolation(ActorInstance, actor, 0);
100+
}
101+
102+
static ActorIsolation forActorInstanceParameter(NominalTypeDecl *actor,
103+
unsigned parameterIndex) {
104+
return ActorIsolation(ActorInstance, actor, parameterIndex + 1);
97105
}
98106

99107
static ActorIsolation forGlobalActor(Type globalActor, bool unsafe) {
@@ -109,6 +117,14 @@ class ActorIsolation {
109117

110118
bool isIndependent() const { return kind == Independent; }
111119

120+
/// Retrieve the parameter to which actor-instance isolation applies.
121+
///
122+
/// Parameter 0 is `self`.
123+
unsigned getActorInstanceParameter() const {
124+
assert(getKind() == ActorInstance);
125+
return parameterIndex;
126+
}
127+
112128
bool isActorIsolated() const {
113129
switch (getKind()) {
114130
case ActorInstance:
@@ -169,7 +185,7 @@ class ActorIsolation {
169185
return true;
170186

171187
case ActorInstance:
172-
return lhs.actor == rhs.actor;
188+
return lhs.actor == rhs.actor && lhs.parameterIndex == rhs.parameterIndex;
173189

174190
case GlobalActor:
175191
case GlobalActorUnsafe:
@@ -183,7 +199,9 @@ class ActorIsolation {
183199
}
184200

185201
friend llvm::hash_code hash_value(const ActorIsolation &state) {
186-
return llvm::hash_combine(state.kind, state.pointer);
202+
return llvm::hash_combine(
203+
state.kind, state.pointer, state.isolatedByPreconcurrency,
204+
state.parameterIndex);
187205
}
188206
};
189207

include/swift/AST/Expr.h

Lines changed: 15 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,80 +1163,19 @@ class DiscardAssignmentExpr : public Expr {
11631163
}
11641164
};
11651165

1166-
/// Describes the actor to which an implicit-async expression will hop.
1167-
struct ImplicitActorHopTarget {
1168-
enum Kind {
1169-
/// The "self" instance.
1170-
InstanceSelf,
1171-
/// A global actor with the given type.
1172-
GlobalActor,
1173-
/// An isolated parameter in a call.
1174-
IsolatedParameter,
1175-
};
1176-
1177-
private:
1178-
/// The lower two bits are the Kind, and the remaining bits are used for
1179-
/// the payload, which might by a TypeBase * (for a global actor) or a
1180-
/// integer value (for an isolated parameter).
1181-
uintptr_t bits;
1182-
1183-
constexpr ImplicitActorHopTarget(uintptr_t bits) : bits(bits) { }
1184-
1185-
public:
1186-
/// Default-initialized to instance "self".
1187-
constexpr ImplicitActorHopTarget() : bits(0) { }
1188-
1189-
static ImplicitActorHopTarget forInstanceSelf() {
1190-
return ImplicitActorHopTarget(InstanceSelf);
1191-
}
1192-
1193-
static ImplicitActorHopTarget forGlobalActor(Type globalActor) {
1194-
uintptr_t bits =
1195-
reinterpret_cast<uintptr_t>(globalActor.getPointer()) | GlobalActor;
1196-
return ImplicitActorHopTarget(bits);
1197-
}
1198-
1199-
static ImplicitActorHopTarget forIsolatedParameter(unsigned index) {
1200-
uintptr_t bits = static_cast<uintptr_t>(index) << 2 | IsolatedParameter;
1201-
return ImplicitActorHopTarget(bits);
1202-
}
1203-
1204-
/// Determine the kind of implicit actor hop being performed.
1205-
Kind getKind() const {
1206-
return static_cast<Kind>(bits & 0x03);
1207-
}
1208-
1209-
operator Kind() const {
1210-
return getKind();
1211-
}
1212-
1213-
/// Retrieve the global actor type for an implicit hop to a global actor.
1214-
Type getGlobalActor() const {
1215-
assert(getKind() == GlobalActor);
1216-
return Type(reinterpret_cast<TypeBase *>(bits & ~0x03));
1217-
}
1218-
1219-
/// Retrieve the (zero-based) parameter index for the isolated parameter
1220-
/// in a call.
1221-
unsigned getIsolatedParameterIndex() const {
1222-
assert(getKind() == IsolatedParameter);
1223-
return bits >> 2;
1224-
}
1225-
};
1226-
1227-
12281166
/// DeclRefExpr - A reference to a value, "x".
12291167
class DeclRefExpr : public Expr {
12301168
/// The declaration pointer.
12311169
ConcreteDeclRef D;
12321170
DeclNameLoc Loc;
1233-
ImplicitActorHopTarget implicitActorHopTarget;
1171+
ActorIsolation implicitActorHopTarget;
12341172

12351173
public:
12361174
DeclRefExpr(ConcreteDeclRef D, DeclNameLoc Loc, bool Implicit,
12371175
AccessSemantics semantics = AccessSemantics::Ordinary,
12381176
Type Ty = Type())
1239-
: Expr(ExprKind::DeclRef, Implicit, Ty), D(D), Loc(Loc) {
1177+
: Expr(ExprKind::DeclRef, Implicit, Ty), D(D), Loc(Loc),
1178+
implicitActorHopTarget(ActorIsolation::forUnspecified()) {
12401179
Bits.DeclRefExpr.Semantics = (unsigned) semantics;
12411180
Bits.DeclRefExpr.FunctionRefKind =
12421181
static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
@@ -1258,15 +1197,15 @@ class DeclRefExpr : public Expr {
12581197

12591198
/// Determine whether this reference needs to happen asynchronously, i.e.,
12601199
/// guarded by hop_to_executor, and if so describe the target.
1261-
Optional<ImplicitActorHopTarget> isImplicitlyAsync() const {
1200+
Optional<ActorIsolation> isImplicitlyAsync() const {
12621201
if (!Bits.DeclRefExpr.IsImplicitlyAsync)
12631202
return None;
12641203

12651204
return implicitActorHopTarget;
12661205
}
12671206

12681207
/// Note that this reference is implicitly async and set the target.
1269-
void setImplicitlyAsync(ImplicitActorHopTarget target) {
1208+
void setImplicitlyAsync(ActorIsolation target) {
12701209
Bits.DeclRefExpr.IsImplicitlyAsync = true;
12711210
implicitActorHopTarget = target;
12721211
}
@@ -1600,12 +1539,13 @@ class UnresolvedDeclRefExpr : public Expr {
16001539
class LookupExpr : public Expr {
16011540
Expr *Base;
16021541
ConcreteDeclRef Member;
1603-
ImplicitActorHopTarget implicitActorHopTarget;
1542+
ActorIsolation implicitActorHopTarget;
16041543

16051544
protected:
16061545
explicit LookupExpr(ExprKind Kind, Expr *base, ConcreteDeclRef member,
16071546
bool Implicit)
1608-
: Expr(Kind, Implicit), Base(base), Member(member) {
1547+
: Expr(Kind, Implicit), Base(base), Member(member),
1548+
implicitActorHopTarget(ActorIsolation::forUnspecified()) {
16091549
Bits.LookupExpr.IsSuper = false;
16101550
Bits.LookupExpr.IsImplicitlyAsync = false;
16111551
Bits.LookupExpr.IsImplicitlyThrows = false;
@@ -1640,15 +1580,15 @@ class LookupExpr : public Expr {
16401580

16411581
/// Determine whether this reference needs to happen asynchronously, i.e.,
16421582
/// guarded by hop_to_executor, and if so describe the target.
1643-
Optional<ImplicitActorHopTarget> isImplicitlyAsync() const {
1583+
Optional<ActorIsolation> isImplicitlyAsync() const {
16441584
if (!Bits.LookupExpr.IsImplicitlyAsync)
16451585
return None;
16461586

16471587
return implicitActorHopTarget;
16481588
}
16491589

16501590
/// Note that this reference is implicitly async and set the target.
1651-
void setImplicitlyAsync(ImplicitActorHopTarget target) {
1591+
void setImplicitlyAsync(ActorIsolation target) {
16521592
Bits.LookupExpr.IsImplicitlyAsync = true;
16531593
implicitActorHopTarget = target;
16541594
}
@@ -4482,12 +4422,13 @@ class ApplyExpr : public Expr {
44824422
/// The list of arguments to call the function with.
44834423
ArgumentList *ArgList;
44844424

4485-
ImplicitActorHopTarget implicitActorHopTarget;
4425+
ActorIsolation implicitActorHopTarget;
44864426

44874427
protected:
44884428
ApplyExpr(ExprKind kind, Expr *fn, ArgumentList *argList, bool implicit,
44894429
Type ty = Type())
4490-
: Expr(kind, implicit, ty), Fn(fn), ArgList(argList) {
4430+
: Expr(kind, implicit, ty), Fn(fn), ArgList(argList),
4431+
implicitActorHopTarget(ActorIsolation::forUnspecified()) {
44914432
assert(ArgList);
44924433
assert(classof((Expr*)this) && "ApplyExpr::classof out of date");
44934434
Bits.ApplyExpr.ThrowsIsSet = false;
@@ -4553,15 +4494,15 @@ class ApplyExpr : public Expr {
45534494
///
45544495
/// When the application is implicitly async, the result describes
45554496
/// the actor to which we need to need to hop.
4556-
Optional<ImplicitActorHopTarget> isImplicitlyAsync() const {
4497+
Optional<ActorIsolation> isImplicitlyAsync() const {
45574498
if (!Bits.ApplyExpr.ImplicitlyAsync)
45584499
return None;
45594500

45604501
return implicitActorHopTarget;
45614502
}
45624503

45634504
/// Note that this application is implicitly async and set the target.
4564-
void setImplicitlyAsync(ImplicitActorHopTarget target) {
4505+
void setImplicitlyAsync(ActorIsolation target) {
45654506
Bits.ApplyExpr.ImplicitlyAsync = true;
45664507
implicitActorHopTarget = target;
45674508
}

lib/AST/Decl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9235,7 +9235,8 @@ ActorIsolation swift::getActorIsolationOfContext(DeclContext *dc) {
92359235
auto actor = selfDecl->getType()->getReferenceStorageReferent()
92369236
->getAnyActor();
92379237
assert(actor && "Bad closure actor isolation?");
9238-
return ActorIsolation::forActorInstance(actor)
9238+
// FIXME: This could be a parameter... or a capture... hmmm.
9239+
return ActorIsolation::forActorInstanceSelf(actor)
92399240
.withPreconcurrency(isolation.preconcurrency());
92409241
}
92419242
}

lib/SILGen/SILGenApply.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3886,7 +3886,7 @@ class CallEmission {
38863886

38873887
Callee callee;
38883888
FormalEvaluationScope initialWritebackScope;
3889-
Optional<ImplicitActorHopTarget> implicitActorHopTarget;
3889+
Optional<ActorIsolation> implicitActorHopTarget;
38903890
bool implicitlyThrows;
38913891

38923892
public:
@@ -3937,7 +3937,7 @@ class CallEmission {
39373937
/// implicitly async, i.e., it requires a hop_to_executor prior to
39383938
/// invoking the sync callee, etc.
39393939
void setImplicitlyAsync(
3940-
Optional<ImplicitActorHopTarget> implicitActorHopTarget) {
3940+
Optional<ActorIsolation> implicitActorHopTarget) {
39413941
this->implicitActorHopTarget = implicitActorHopTarget;
39423942
}
39433943

@@ -4573,7 +4573,7 @@ RValue SILGenFunction::emitApply(
45734573
ArrayRef<ManagedValue> args,
45744574
const CalleeTypeInfo &calleeTypeInfo,
45754575
ApplyOptions options, SGFContext evalContext,
4576-
Optional<ImplicitActorHopTarget> implicitActorHopTarget) {
4576+
Optional<ActorIsolation> implicitActorHopTarget) {
45774577
auto substFnType = calleeTypeInfo.substFnType;
45784578
auto substResultType = calleeTypeInfo.substResultType;
45794579

@@ -4672,18 +4672,24 @@ RValue SILGenFunction::emitApply(
46724672

46734673
SILValue executor;
46744674
switch (*implicitActorHopTarget) {
4675-
case ImplicitActorHopTarget::InstanceSelf:
4676-
executor = emitLoadActorExecutor(loc, args.back());
4675+
case ActorIsolation::ActorInstance:
4676+
if (unsigned paramIndex =
4677+
implicitActorHopTarget->getActorInstanceParameter()) {
4678+
executor = emitLoadActorExecutor(loc, args[paramIndex-1]);
4679+
} else {
4680+
executor = emitLoadActorExecutor(loc, args.back());
4681+
}
46774682
break;
46784683

4679-
case ImplicitActorHopTarget::GlobalActor:
4684+
case ActorIsolation::GlobalActor:
4685+
case ActorIsolation::GlobalActorUnsafe:
46804686
executor = emitLoadGlobalActorExecutor(
46814687
implicitActorHopTarget->getGlobalActor());
46824688
break;
46834689

4684-
case ImplicitActorHopTarget::IsolatedParameter:
4685-
executor = emitLoadActorExecutor(
4686-
loc, args[implicitActorHopTarget->getIsolatedParameterIndex()]);
4690+
case ActorIsolation::Unspecified:
4691+
case ActorIsolation::Independent:
4692+
llvm_unreachable("Not isolated");
46874693
break;
46884694
}
46894695

@@ -5897,7 +5903,7 @@ RValue SILGenFunction::emitGetAccessor(
58975903
PreparedArguments &&subscriptIndices,
58985904
SGFContext c,
58995905
bool isOnSelfParameter,
5900-
Optional<ImplicitActorHopTarget> implicitActorHopTarget) {
5906+
Optional<ActorIsolation> implicitActorHopTarget) {
59015907
// Scope any further writeback just within this operation.
59025908
FormalEvaluationScope writebackScope(*this);
59035909

lib/SILGen/SILGenFunction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,7 +1451,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
14511451
bool isDirectAccessorUse,
14521452
PreparedArguments &&optionalSubscripts, SGFContext C,
14531453
bool isOnSelfParameter,
1454-
Optional<ImplicitActorHopTarget> implicitActorHopTarget = None);
1454+
Optional<ActorIsolation> implicitActorHopTarget = None);
14551455

14561456
void emitSetAccessor(SILLocation loc, SILDeclRef setter,
14571457
SubstitutionMap substitutions,
@@ -1684,7 +1684,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
16841684
ArrayRef<ManagedValue> args,
16851685
const CalleeTypeInfo &calleeTypeInfo, ApplyOptions options,
16861686
SGFContext evalContext,
1687-
Optional<ImplicitActorHopTarget> implicitActorHopTarget);
1687+
Optional<ActorIsolation> implicitActorHopTarget);
16881688

16891689
RValue emitApplyOfDefaultArgGenerator(SILLocation loc,
16901690
ConcreteDeclRef defaultArgsOwner,

lib/SILGen/SILGenLValue.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,23 +1648,13 @@ namespace {
16481648
RValue rvalue;
16491649
FormalEvaluationScope scope(SGF);
16501650

1651-
// FIXME: This somewhat silly, because the original expression should
1652-
// already have one of these.
1653-
Optional<ImplicitActorHopTarget> implicitActorHopTarget;
1654-
if (ActorIso) {
1655-
implicitActorHopTarget = ActorIso->isGlobalActor()
1656-
? ImplicitActorHopTarget::forGlobalActor(
1657-
ActorIso->getGlobalActor())
1658-
: ImplicitActorHopTarget::forInstanceSelf();
1659-
}
1660-
16611651
auto args =
16621652
std::move(*this).prepareAccessorArgs(SGF, loc, base, getter);
16631653

16641654
rvalue = SGF.emitGetAccessor(
16651655
loc, getter, Substitutions, std::move(args.base), IsSuper,
16661656
IsDirectAccessorUse, std::move(args.Indices), c,
1667-
IsOnSelfParameter, implicitActorHopTarget);
1657+
IsOnSelfParameter, ActorIso);
16681658

16691659
return rvalue;
16701660
}

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4437,6 +4437,7 @@ void SILGenFunction::emitProtocolWitness(
44374437

44384438
// For an instance actor, get the actor 'self'.
44394439
if (*enterIsolation == ActorIsolation::ActorInstance) {
4440+
assert(enterIsolation->getActorInstanceParameter() == 0 && "Not self?");
44404441
auto actorSelfVal = origParams.back();
44414442

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

0 commit comments

Comments
 (0)