@@ -107,24 +107,26 @@ class SILIsolationInfo {
107
107
108
108
private:
109
109
Kind kind;
110
- // clang-format off
111
- std::variant<
112
- // Used for actor isolated when we have ActorIsolation info from the AST.
113
- ActorIsolation,
114
- // The task isolated parameter when we find a task isolated value.
115
- SILValue
116
- > data;
117
- // clang-format on
118
110
119
- SILIsolationInfo (ActorIsolation actorIsolation)
120
- : kind(Actor), data(actorIsolation) {}
111
+ // / The actor isolation if this value has one. The default unspecified case
112
+ // / otherwise.
113
+ ActorIsolation actorIsolation;
114
+
115
+ // / This is the value that we got isolation from if we were able to find
116
+ // / one. Used for isolation history.
117
+ SILValue isolationSource;
118
+
119
+ SILIsolationInfo (ActorIsolation actorIsolation, SILValue isolationSource)
120
+ : kind(Actor), actorIsolation(actorIsolation),
121
+ isolationSource (isolationSource) {}
121
122
122
- SILIsolationInfo (Kind kind, SILValue value) : kind(kind), data(value) {}
123
+ SILIsolationInfo (Kind kind, SILValue isolationSource)
124
+ : kind(kind), actorIsolation(), isolationSource(isolationSource) {}
123
125
124
- SILIsolationInfo (Kind kind) : kind(kind), data () {}
126
+ SILIsolationInfo (Kind kind) : kind(kind), actorIsolation () {}
125
127
126
128
public:
127
- SILIsolationInfo () : kind(Kind::Unknown), data () {}
129
+ SILIsolationInfo () : kind(Kind::Unknown), actorIsolation () {}
128
130
129
131
operator bool () const { return kind != Kind::Unknown; }
130
132
@@ -147,47 +149,50 @@ class SILIsolationInfo {
147
149
148
150
ActorIsolation getActorIsolation () const {
149
151
assert (kind == Actor);
150
- assert (std::holds_alternative<ActorIsolation>(data) &&
151
- " Doesn't have an actor isolation?!" );
152
- return std::get<ActorIsolation>(data);
152
+ return actorIsolation;
153
153
}
154
154
155
- SILValue getTaskIsolatedValue () const {
156
- assert (kind == Task);
157
- assert (std::holds_alternative<SILValue>(data) &&
158
- " Doesn't have a task isolated value " );
159
- return std::get<SILValue>(data) ;
155
+ // If we are actor or task isolated and could find a specific value that
156
+ // caused the isolation, put it here. Used for isolation history.
157
+ SILValue getIsolatedValue () const {
158
+ assert (kind == Task || kind == Actor );
159
+ return isolationSource ;
160
160
}
161
161
162
162
bool hasActorIsolation () const { return kind == Actor; }
163
163
164
- bool hasTaskIsolatedValue () const {
165
- return kind == Task && std::holds_alternative<SILValue>(data );
164
+ bool hasIsolatedValue () const {
165
+ return ( kind == Task || kind == Actor) && bool (isolationSource );
166
166
}
167
167
168
168
[[nodiscard]] SILIsolationInfo merge (SILIsolationInfo other) const ;
169
169
170
- SILIsolationInfo withActorIsolated (ActorIsolation isolation) {
171
- return SILIsolationInfo::getActorIsolated (isolation);
170
+ SILIsolationInfo withActorIsolated (SILValue isolatedValue,
171
+ ActorIsolation isolation) {
172
+ return SILIsolationInfo::getActorIsolated (isolatedValue, isolation);
172
173
}
173
174
174
175
static SILIsolationInfo getDisconnected () { return {Kind::Disconnected}; }
175
176
176
- static SILIsolationInfo getActorIsolated (ActorIsolation actorIsolation) {
177
- return {actorIsolation};
177
+ static SILIsolationInfo getActorIsolated (SILValue isolatedValue,
178
+ ActorIsolation actorIsolation) {
179
+ return {actorIsolation, isolatedValue};
178
180
}
179
181
180
- static SILIsolationInfo getActorIsolated (NominalTypeDecl *typeDecl) {
182
+ static SILIsolationInfo getActorIsolated (SILValue isolatedValue,
183
+ NominalTypeDecl *typeDecl) {
181
184
if (typeDecl->isActor ())
182
- return {ActorIsolation::forActorInstanceSelf (typeDecl)};
185
+ return {ActorIsolation::forActorInstanceSelf (typeDecl), isolatedValue };
183
186
auto isolation = swift::getActorIsolation (typeDecl);
184
187
if (isolation.isGlobalActor ())
185
- return {isolation};
188
+ return {isolation, isolatedValue };
186
189
return {};
187
190
}
188
191
189
- static SILIsolationInfo getGlobalActorIsolated (Type globalActorType) {
190
- return getActorIsolated (ActorIsolation::forGlobalActor (globalActorType));
192
+ static SILIsolationInfo getGlobalActorIsolated (SILValue value,
193
+ Type globalActorType) {
194
+ return getActorIsolated (value,
195
+ ActorIsolation::forGlobalActor (globalActorType));
191
196
}
192
197
193
198
static SILIsolationInfo getTaskIsolated (SILValue value) {
@@ -200,7 +205,19 @@ class SILIsolationInfo {
200
205
// / Attempt to infer the isolation region info for \p arg.
201
206
static SILIsolationInfo get (SILFunctionArgument *arg);
202
207
203
- bool operator ==(const SILIsolationInfo &other) const ;
208
+ bool hasSameIsolation (ActorIsolation actorIsolation) const ;
209
+
210
+ // / Returns true if \p this and \p other have the same isolation. It allows
211
+ // / for the isolated values if any to not match.
212
+ // /
213
+ // / This is useful if one has two non-Sendable values projected from the same
214
+ // / actor or global actor isolated value. E.x.: two different ref_element_addr
215
+ // / from the same actor.
216
+ bool hasSameIsolation (const SILIsolationInfo &other) const ;
217
+
218
+ // / Returns true if this SILIsolationInfo is deeply equal to other. This means
219
+ // / that the isolation and the isolated value match.
220
+ bool isEqual (const SILIsolationInfo &other) const ;
204
221
205
222
void Profile (llvm::FoldingSetNodeID &id) const ;
206
223
};
@@ -444,20 +461,31 @@ class TransferringOperand {
444
461
ValueType value;
445
462
446
463
// / The dynamic isolation info of the region of value when we transferred.
464
+ // /
465
+ // / This will contain the isolated value if we found one.
447
466
SILIsolationInfo isolationInfo;
448
467
449
- TransferringOperand (ValueType newValue, SILIsolationInfo isolationRegionInfo)
450
- : value(newValue), isolationInfo(isolationRegionInfo) {
468
+ // / The dynamic isolation history at this point.
469
+ IsolationHistory isolationHistory;
470
+
471
+ TransferringOperand (ValueType newValue, SILIsolationInfo isolationRegionInfo,
472
+ IsolationHistory isolationHistory)
473
+ : value(newValue), isolationInfo(isolationRegionInfo),
474
+ isolationHistory (isolationHistory) {
451
475
assert (isolationInfo && " Should never see unknown isolation info" );
452
476
}
453
477
454
478
public:
455
479
TransferringOperand (Operand *op, bool isClosureCaptured,
456
- SILIsolationInfo isolationRegionInfo)
457
- : TransferringOperand({op, isClosureCaptured}, isolationRegionInfo) {}
480
+ SILIsolationInfo isolationRegionInfo,
481
+ IsolationHistory isolationHistory)
482
+ : TransferringOperand({op, isClosureCaptured}, isolationRegionInfo,
483
+ isolationHistory) {}
458
484
explicit TransferringOperand (Operand *op,
459
- SILIsolationInfo isolationRegionInfo)
460
- : TransferringOperand({op, false }, isolationRegionInfo) {}
485
+ SILIsolationInfo isolationRegionInfo,
486
+ IsolationHistory isolationHistory)
487
+ : TransferringOperand({op, false }, isolationRegionInfo,
488
+ isolationHistory) {}
461
489
462
490
operator bool () const { return bool (value.getPointer ()); }
463
491
@@ -471,6 +499,8 @@ class TransferringOperand {
471
499
472
500
SILIsolationInfo getIsolationInfo () const { return isolationInfo; }
473
501
502
+ IsolationHistory getIsolationHistory () const { return isolationHistory; }
503
+
474
504
unsigned getOperandNumber () const { return getOperand ()->getOperandNumber (); }
475
505
476
506
void print (llvm::raw_ostream &os) const {
@@ -483,14 +513,17 @@ class TransferringOperand {
483
513
484
514
static void Profile (llvm::FoldingSetNodeID &id, Operand *op,
485
515
bool isClosureCaptured,
486
- SILIsolationInfo isolationRegionInfo) {
516
+ SILIsolationInfo isolationRegionInfo,
517
+ IsolationHistory isolationHistory) {
487
518
id.AddPointer (op);
488
519
id.AddBoolean (isClosureCaptured);
489
520
isolationRegionInfo.Profile (id);
521
+ id.AddPointer (isolationHistory.getHead ());
490
522
}
491
523
492
524
void Profile (llvm::FoldingSetNodeID &id) const {
493
- Profile (id, getOperand (), isClosureCaptured (), isolationInfo);
525
+ Profile (id, getOperand (), isClosureCaptured (), isolationInfo,
526
+ isolationHistory);
494
527
}
495
528
496
529
SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
@@ -1134,7 +1167,8 @@ struct PartitionOpEvaluator {
1134
1167
if (transferredRegionIsolation.isActorIsolated ()) {
1135
1168
if (auto calleeIsolationInfo =
1136
1169
SILIsolationInfo::get (op.getSourceInst ())) {
1137
- if (transferredRegionIsolation == calleeIsolationInfo) {
1170
+ if (transferredRegionIsolation.hasSameIsolation (
1171
+ calleeIsolationInfo)) {
1138
1172
return ;
1139
1173
}
1140
1174
}
@@ -1151,7 +1185,8 @@ struct PartitionOpEvaluator {
1151
1185
1152
1186
// Mark op.getOpArgs()[0] as transferred.
1153
1187
auto *ptrSet = ptrSetFactory.emplace (
1154
- op.getSourceOp (), isClosureCapturedElt, transferredRegionIsolation);
1188
+ op.getSourceOp (), isClosureCapturedElt, transferredRegionIsolation,
1189
+ p.getIsolationHistory ());
1155
1190
p.markTransferred (op.getOpArgs ()[0 ], ptrSet);
1156
1191
return ;
1157
1192
}
@@ -1227,7 +1262,8 @@ struct PartitionOpEvaluator {
1227
1262
if (shouldTryToSquelchErrors ()) {
1228
1263
if (auto isolationInfo = SILIsolationInfo::get (op.getSourceInst ())) {
1229
1264
if (isolationInfo.isActorIsolated () &&
1230
- isolationInfo == SILIsolationInfo::get (transferringOp->getUser ()))
1265
+ isolationInfo.hasSameIsolation (
1266
+ SILIsolationInfo::get (transferringOp->getUser ())))
1231
1267
return ;
1232
1268
}
1233
1269
@@ -1237,8 +1273,8 @@ struct PartitionOpEvaluator {
1237
1273
if (auto functionIsolation =
1238
1274
transferringOp->getUser ()->getFunction ()->getActorIsolation ()) {
1239
1275
if (functionIsolation.isActorIsolated () &&
1240
- SILIsolationInfo::getActorIsolated (functionIsolation) ==
1241
- SILIsolationInfo::get (transferringOp-> getUser () ))
1276
+ SILIsolationInfo::get (transferringOp-> getUser ())
1277
+ . hasSameIsolation (functionIsolation ))
1242
1278
return ;
1243
1279
}
1244
1280
}
0 commit comments