Skip to content

Commit 3f26d08

Browse files
committed
[region-isolation] Add the ability in SILIsolationInfo to represent a disconnected value that is nonisolated(unsafe).
1 parent 4b29089 commit 3f26d08

File tree

5 files changed

+78
-31
lines changed

5 files changed

+78
-31
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ class ActorIsolation {
170170
return (kind == Nonisolated) || (kind == NonisolatedUnsafe);
171171
}
172172

173+
bool isNonisolatedUnsafe() const { return kind == NonisolatedUnsafe; }
174+
173175
/// Retrieve the parameter to which actor-instance isolation applies.
174176
///
175177
/// Parameter 0 is `self`.

include/swift/SILOptimizer/Analysis/RegionAnalysis.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ using TrackedValueFlagSet = OptionSet<TrackableValueFlag>;
123123
class regionanalysisimpl::TrackableValueState {
124124
unsigned id;
125125
TrackedValueFlagSet flagSet = {TrackableValueFlag::isMayAlias};
126-
SILIsolationInfo regionInfo = SILIsolationInfo::getDisconnected();
126+
SILIsolationInfo regionInfo =
127+
SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/);
127128

128129
public:
129130
TrackableValueState(unsigned newID) : id(newID) {}

include/swift/SILOptimizer/Utils/SILIsolationInfo.h

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,14 @@ class SILIsolationInfo {
109109
/// Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
110110
///
111111
/// Unknown means no information. We error when merging on it.
112-
enum Kind {
112+
enum Kind : uint8_t {
113113
Unknown,
114114
Disconnected,
115115
Task,
116116
Actor,
117117
};
118118

119119
private:
120-
Kind kind;
121-
122120
/// The actor isolation if this value has one. The default unspecified case
123121
/// otherwise.
124122
ActorIsolation actorIsolation;
@@ -131,11 +129,14 @@ class SILIsolationInfo {
131129
/// derived isolatedValue from.
132130
ActorInstance actorInstance;
133131

132+
unsigned kind : 8;
133+
unsigned unsafeNonIsolated : 1;
134+
134135
SILIsolationInfo(SILValue isolatedValue, SILValue actorInstance,
135-
ActorIsolation actorIsolation)
136-
: kind(Actor), actorIsolation(actorIsolation),
137-
isolatedValue(isolatedValue),
138-
actorInstance(ActorInstance::getForValue(actorInstance)) {
136+
ActorIsolation actorIsolation, bool isUnsafeNonIsolated)
137+
: actorIsolation(actorIsolation), isolatedValue(isolatedValue),
138+
actorInstance(ActorInstance::getForValue(actorInstance)), kind(Actor),
139+
unsafeNonIsolated(isUnsafeNonIsolated) {
139140
assert((!actorInstance ||
140141
(actorIsolation.getKind() == ActorIsolation::ActorInstance &&
141142
actorInstance->getType()
@@ -146,31 +147,44 @@ class SILIsolationInfo {
146147
}
147148

148149
SILIsolationInfo(SILValue isolatedValue, ActorInstance actorInstance,
149-
ActorIsolation actorIsolation)
150-
: kind(Actor), actorIsolation(actorIsolation),
151-
isolatedValue(isolatedValue), actorInstance(actorInstance) {
150+
ActorIsolation actorIsolation, bool isUnsafeNonIsolated)
151+
: actorIsolation(actorIsolation), isolatedValue(isolatedValue),
152+
actorInstance(actorInstance), kind(Actor),
153+
unsafeNonIsolated(isUnsafeNonIsolated) {
152154
assert(actorInstance);
153155
assert(actorIsolation.getKind() == ActorIsolation::ActorInstance);
154156
}
155157

156158
SILIsolationInfo(Kind kind, SILValue isolatedValue)
157-
: kind(kind), actorIsolation(), isolatedValue(isolatedValue) {}
159+
: actorIsolation(), isolatedValue(isolatedValue), kind(kind),
160+
unsafeNonIsolated(false) {}
158161

159-
SILIsolationInfo(Kind kind) : kind(kind), actorIsolation() {}
162+
SILIsolationInfo(Kind kind, bool isUnsafeNonIsolated)
163+
: actorIsolation(), kind(kind), unsafeNonIsolated(isUnsafeNonIsolated) {}
160164

161165
public:
162-
SILIsolationInfo() : kind(Kind::Unknown), actorIsolation() {}
166+
SILIsolationInfo()
167+
: actorIsolation(), kind(Kind::Unknown), unsafeNonIsolated(false) {}
163168

164169
operator bool() const { return kind != Kind::Unknown; }
165170

166-
operator Kind() const { return kind; }
171+
operator Kind() const { return getKind(); }
167172

168-
Kind getKind() const { return kind; }
173+
Kind getKind() const { return Kind(kind); }
169174

170175
bool isDisconnected() const { return kind == Kind::Disconnected; }
171176
bool isActorIsolated() const { return kind == Kind::Actor; }
172177
bool isTaskIsolated() const { return kind == Kind::Task; }
173178

179+
bool isUnsafeNonIsolated() const { return unsafeNonIsolated; }
180+
181+
SILIsolationInfo withUnsafeNonIsolated(bool newValue = true) const {
182+
assert(*this && "Cannot be unknown");
183+
auto self = *this;
184+
self.unsafeNonIsolated = newValue;
185+
return self;
186+
}
187+
174188
void print(llvm::raw_ostream &os) const;
175189

176190
SWIFT_DEBUG_DUMP {
@@ -212,7 +226,9 @@ class SILIsolationInfo {
212226

213227
[[nodiscard]] SILIsolationInfo merge(SILIsolationInfo other) const;
214228

215-
static SILIsolationInfo getDisconnected() { return {Kind::Disconnected}; }
229+
static SILIsolationInfo getDisconnected(bool isUnsafeNonIsolated) {
230+
return {Kind::Disconnected, isUnsafeNonIsolated};
231+
}
216232

217233
/// Create an actor isolation for a value that we know is actor isolated to a
218234
/// specific actor, but we do not know the specific instance yet.
@@ -228,7 +244,8 @@ class SILIsolationInfo {
228244
static SILIsolationInfo
229245
getFlowSensitiveActorIsolated(SILValue isolatedValue,
230246
ActorIsolation actorIsolation) {
231-
return {isolatedValue, SILValue(), actorIsolation};
247+
return {isolatedValue, SILValue(), actorIsolation,
248+
false /*nonisolated(unsafe)*/};
232249
}
233250

234251
/// Only use this as a fallback if we cannot find better information.
@@ -237,7 +254,8 @@ class SILIsolationInfo {
237254
if (crossing.getCalleeIsolation().isActorIsolated()) {
238255
// SIL level, just let it through
239256
return SILIsolationInfo(SILValue(), SILValue(),
240-
crossing.getCalleeIsolation());
257+
crossing.getCalleeIsolation(),
258+
false /*nonisolated(unsafe)*/);
241259
}
242260

243261
return {};
@@ -253,7 +271,8 @@ class SILIsolationInfo {
253271
return {};
254272
}
255273
return {isolatedValue, actorInstance,
256-
ActorIsolation::forActorInstanceSelf(typeDecl)};
274+
ActorIsolation::forActorInstanceSelf(typeDecl),
275+
false /*nonisolated(unsafe)*/};
257276
}
258277

259278
static SILIsolationInfo getActorInstanceIsolated(SILValue isolatedValue,
@@ -266,7 +285,8 @@ class SILIsolationInfo {
266285
return {};
267286
}
268287
return {isolatedValue, actorInstance,
269-
ActorIsolation::forActorInstanceSelf(typeDecl)};
288+
ActorIsolation::forActorInstanceSelf(typeDecl),
289+
false /*nonisolated(unsafe)*/};
270290
}
271291

272292
/// A special actor instance isolated for partial apply cases where we do not
@@ -281,13 +301,15 @@ class SILIsolationInfo {
281301
return {};
282302
}
283303
return {isolatedValue, SILValue(),
284-
ActorIsolation::forActorInstanceSelf(typeDecl)};
304+
ActorIsolation::forActorInstanceSelf(typeDecl),
305+
false /*nonisolated(unsafe)*/};
285306
}
286307

287308
static SILIsolationInfo getGlobalActorIsolated(SILValue value,
288309
Type globalActorType) {
289310
return {value, SILValue() /*no actor instance*/,
290-
ActorIsolation::forGlobalActor(globalActorType)};
311+
ActorIsolation::forGlobalActor(globalActorType),
312+
false /*nonisolated(unsafe)*/};
291313
}
292314

293315
static SILIsolationInfo getGlobalActorIsolated(SILValue value,

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
354354
return info;
355355

356356
if (crossing->getCalleeIsolation().isNonisolated()) {
357-
return SILIsolationInfo::getDisconnected();
357+
return SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/);
358358
}
359359
}
360360
}
@@ -386,7 +386,7 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
386386
((fArg->isClosureCapture() &&
387387
fArg->getFunction()->getLoweredFunctionType()->isSendable()) ||
388388
fArg->isSending()))
389-
return SILIsolationInfo::getDisconnected();
389+
return SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/);
390390

391391
// Before we do anything further, see if we have an isolated parameter. This
392392
// handles isolated self and specifically marked isolated.
@@ -408,7 +408,7 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
408408
if (auto declRef = fArg->getFunction()->getDeclRef()) {
409409
if (declRef.kind == SILDeclRef::Kind::Allocator) {
410410
if (fArg->getFunction()->getActorIsolation().isActorInstanceIsolated()) {
411-
return SILIsolationInfo::getDisconnected();
411+
return SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/);
412412
}
413413
}
414414

@@ -447,21 +447,33 @@ void SILIsolationInfo::print(llvm::raw_ostream &os) const {
447447
return;
448448
case Disconnected:
449449
os << "disconnected";
450+
if (unsafeNonIsolated) {
451+
os << ": nonisolated(unsafe)";
452+
}
450453
return;
451454
case Actor:
452455
if (ActorInstance instance = getActorInstance()) {
453456
switch (instance.getKind()) {
454457
case ActorInstance::Kind::Value: {
455458
SILValue value = instance.getValue();
456459
if (auto name = VariableNameInferrer::inferName(value)) {
457-
os << "'" << *name << "'-isolated\n";
460+
os << "'" << *name << "'-isolated";
461+
if (unsafeNonIsolated) {
462+
os << ": nonisolated(unsafe)";
463+
}
464+
os << "\n";
458465
os << "instance: " << *value;
466+
459467
return;
460468
}
461469
break;
462470
}
463471
case ActorInstance::Kind::ActorAccessorInit:
464-
os << "'self'-isolated\n";
472+
os << "'self'-isolated";
473+
if (unsafeNonIsolated) {
474+
os << ": nonisolated(unsafe)";
475+
}
476+
os << '\n';
465477
os << "instance: actor accessor init\n";
466478
return;
467479
}
@@ -470,14 +482,24 @@ void SILIsolationInfo::print(llvm::raw_ostream &os) const {
470482
if (getActorIsolation().getKind() == ActorIsolation::ActorInstance) {
471483
if (auto *vd = getActorIsolation().getActorInstance()) {
472484
os << "'" << vd->getBaseIdentifier() << "'-isolated";
485+
if (unsafeNonIsolated) {
486+
os << ": nonisolated(unsafe)";
487+
}
473488
return;
474489
}
475490
}
476491

477492
getActorIsolation().printForDiagnostics(os);
493+
if (unsafeNonIsolated) {
494+
os << ": nonisolated(unsafe)";
495+
}
478496
return;
479497
case Task:
480-
os << "task-isolated\n";
498+
os << "task-isolated";
499+
if (unsafeNonIsolated) {
500+
os << ": nonisolated(unsafe)";
501+
}
502+
os << '\n';
481503
os << "instance: " << *getIsolatedValue();
482504
return;
483505
}

unittests/SILOptimizer/PartitionUtilsTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct MockedPartitionOpEvaluator final
4747

4848
// Just say that we always have a disconnected value.
4949
SILIsolationInfo getIsolationRegionInfo(Element elt) const {
50-
return SILIsolationInfo::getDisconnected();
50+
return SILIsolationInfo::getDisconnected(false /*isUnsafeNonIsolated*/);
5151
}
5252

5353
bool shouldTryToSquelchErrors() const { return false; }
@@ -89,7 +89,7 @@ struct MockedPartitionOpEvaluatorWithFailureCallback final
8989

9090
// Just say that we always have a disconnected value.
9191
SILIsolationInfo getIsolationRegionInfo(Element elt) const {
92-
return SILIsolationInfo::getDisconnected();
92+
return SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/);
9393
}
9494

9595
bool shouldTryToSquelchErrors() const { return false; }

0 commit comments

Comments
 (0)