@@ -107,24 +107,26 @@ class SILIsolationInfo {
107107
108108private:
109109 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
118110
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) {}
121122
122- SILIsolationInfo (Kind kind, SILValue value) : kind(kind), data(value) {}
123+ SILIsolationInfo (Kind kind, SILValue isolationSource)
124+ : kind(kind), actorIsolation(), isolationSource(isolationSource) {}
123125
124- SILIsolationInfo (Kind kind) : kind(kind), data () {}
126+ SILIsolationInfo (Kind kind) : kind(kind), actorIsolation () {}
125127
126128public:
127- SILIsolationInfo () : kind(Kind::Unknown), data () {}
129+ SILIsolationInfo () : kind(Kind::Unknown), actorIsolation () {}
128130
129131 operator bool () const { return kind != Kind::Unknown; }
130132
@@ -147,47 +149,50 @@ class SILIsolationInfo {
147149
148150 ActorIsolation getActorIsolation () const {
149151 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;
153153 }
154154
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 ;
160160 }
161161
162162 bool hasActorIsolation () const { return kind == Actor; }
163163
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 );
166166 }
167167
168168 [[nodiscard]] SILIsolationInfo merge (SILIsolationInfo other) const ;
169169
170- SILIsolationInfo withActorIsolated (ActorIsolation isolation) {
171- return SILIsolationInfo::getActorIsolated (isolation);
170+ SILIsolationInfo withActorIsolated (SILValue isolatedValue,
171+ ActorIsolation isolation) {
172+ return SILIsolationInfo::getActorIsolated (isolatedValue, isolation);
172173 }
173174
174175 static SILIsolationInfo getDisconnected () { return {Kind::Disconnected}; }
175176
176- static SILIsolationInfo getActorIsolated (ActorIsolation actorIsolation) {
177- return {actorIsolation};
177+ static SILIsolationInfo getActorIsolated (SILValue isolatedValue,
178+ ActorIsolation actorIsolation) {
179+ return {actorIsolation, isolatedValue};
178180 }
179181
180- static SILIsolationInfo getActorIsolated (NominalTypeDecl *typeDecl) {
182+ static SILIsolationInfo getActorIsolated (SILValue isolatedValue,
183+ NominalTypeDecl *typeDecl) {
181184 if (typeDecl->isActor ())
182- return {ActorIsolation::forActorInstanceSelf (typeDecl)};
185+ return {ActorIsolation::forActorInstanceSelf (typeDecl), isolatedValue };
183186 auto isolation = swift::getActorIsolation (typeDecl);
184187 if (isolation.isGlobalActor ())
185- return {isolation};
188+ return {isolation, isolatedValue };
186189 return {};
187190 }
188191
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));
191196 }
192197
193198 static SILIsolationInfo getTaskIsolated (SILValue value) {
@@ -200,7 +205,19 @@ class SILIsolationInfo {
200205 // / Attempt to infer the isolation region info for \p arg.
201206 static SILIsolationInfo get (SILFunctionArgument *arg);
202207
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 ;
204221
205222 void Profile (llvm::FoldingSetNodeID &id) const ;
206223};
@@ -444,20 +461,31 @@ class TransferringOperand {
444461 ValueType value;
445462
446463 // / The dynamic isolation info of the region of value when we transferred.
464+ // /
465+ // / This will contain the isolated value if we found one.
447466 SILIsolationInfo isolationInfo;
448467
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) {
451475 assert (isolationInfo && " Should never see unknown isolation info" );
452476 }
453477
454478public:
455479 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) {}
458484 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) {}
461489
462490 operator bool () const { return bool (value.getPointer ()); }
463491
@@ -471,6 +499,8 @@ class TransferringOperand {
471499
472500 SILIsolationInfo getIsolationInfo () const { return isolationInfo; }
473501
502+ IsolationHistory getIsolationHistory () const { return isolationHistory; }
503+
474504 unsigned getOperandNumber () const { return getOperand ()->getOperandNumber (); }
475505
476506 void print (llvm::raw_ostream &os) const {
@@ -483,14 +513,17 @@ class TransferringOperand {
483513
484514 static void Profile (llvm::FoldingSetNodeID &id, Operand *op,
485515 bool isClosureCaptured,
486- SILIsolationInfo isolationRegionInfo) {
516+ SILIsolationInfo isolationRegionInfo,
517+ IsolationHistory isolationHistory) {
487518 id.AddPointer (op);
488519 id.AddBoolean (isClosureCaptured);
489520 isolationRegionInfo.Profile (id);
521+ id.AddPointer (isolationHistory.getHead ());
490522 }
491523
492524 void Profile (llvm::FoldingSetNodeID &id) const {
493- Profile (id, getOperand (), isClosureCaptured (), isolationInfo);
525+ Profile (id, getOperand (), isClosureCaptured (), isolationInfo,
526+ isolationHistory);
494527 }
495528
496529 SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
@@ -1134,7 +1167,8 @@ struct PartitionOpEvaluator {
11341167 if (transferredRegionIsolation.isActorIsolated ()) {
11351168 if (auto calleeIsolationInfo =
11361169 SILIsolationInfo::get (op.getSourceInst ())) {
1137- if (transferredRegionIsolation == calleeIsolationInfo) {
1170+ if (transferredRegionIsolation.hasSameIsolation (
1171+ calleeIsolationInfo)) {
11381172 return ;
11391173 }
11401174 }
@@ -1151,7 +1185,8 @@ struct PartitionOpEvaluator {
11511185
11521186 // Mark op.getOpArgs()[0] as transferred.
11531187 auto *ptrSet = ptrSetFactory.emplace (
1154- op.getSourceOp (), isClosureCapturedElt, transferredRegionIsolation);
1188+ op.getSourceOp (), isClosureCapturedElt, transferredRegionIsolation,
1189+ p.getIsolationHistory ());
11551190 p.markTransferred (op.getOpArgs ()[0 ], ptrSet);
11561191 return ;
11571192 }
@@ -1227,7 +1262,8 @@ struct PartitionOpEvaluator {
12271262 if (shouldTryToSquelchErrors ()) {
12281263 if (auto isolationInfo = SILIsolationInfo::get (op.getSourceInst ())) {
12291264 if (isolationInfo.isActorIsolated () &&
1230- isolationInfo == SILIsolationInfo::get (transferringOp->getUser ()))
1265+ isolationInfo.hasSameIsolation (
1266+ SILIsolationInfo::get (transferringOp->getUser ())))
12311267 return ;
12321268 }
12331269
@@ -1237,8 +1273,8 @@ struct PartitionOpEvaluator {
12371273 if (auto functionIsolation =
12381274 transferringOp->getUser ()->getFunction ()->getActorIsolation ()) {
12391275 if (functionIsolation.isActorIsolated () &&
1240- SILIsolationInfo::getActorIsolated (functionIsolation) ==
1241- SILIsolationInfo::get (transferringOp-> getUser () ))
1276+ SILIsolationInfo::get (transferringOp-> getUser ())
1277+ . hasSameIsolation (functionIsolation ))
12421278 return ;
12431279 }
12441280 }
0 commit comments