@@ -125,24 +125,133 @@ enum class TrackableValueFlag {
125
125
126
126
// / Set to true if this TrackableValue's representative is Sendable.
127
127
isSendable = 0x2 ,
128
-
129
- // / Set to true if this TrackableValue is a non-sendable object derived from
130
- // / an actor. Example: a value loaded from a ref_element_addr from an actor.
131
- // /
132
- // / NOTE: We track values with an actor representative even though actors are
133
- // / sendable to be able to properly identify values that escape an actor since
134
- // / if we escape an actor into a closure, we want to mark the closure as actor
135
- // / derived.
136
- isActorDerived = 0x4 ,
137
128
};
138
129
139
130
using TrackedValueFlagSet = OptionSet<TrackableValueFlag>;
140
131
132
+ class ValueIsolationRegionInfo {
133
+ public:
134
+ // / The lattice is:
135
+ // /
136
+ // / Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
137
+ // /
138
+ // / Unknown means no information. We error when merging on it.
139
+ enum Kind {
140
+ Unknown,
141
+ Disconnected,
142
+ Actor,
143
+ };
144
+
145
+ private:
146
+ Kind kind;
147
+
148
+ // / When this is set it corresponds to a specific ActorIsolation from the AST
149
+ // / that we found.
150
+ // /
151
+ // / NOTE: actorInstanceType and actorIsolation should never be both set!
152
+ std::optional<ActorIsolation> actorIsolation;
153
+
154
+ // / When this is set it corresponds to a specific Actor type that we
155
+ // / identified as being actor isolated from a SIL level type. We do not have
156
+ // / the ActorIsolation information, so this is artificial.
157
+ // /
158
+ // / NOTE: actorInstanceType and actorIsolation should never be both set!
159
+ NominalTypeDecl *actorInstanceType = nullptr ;
160
+
161
+ ValueIsolationRegionInfo (Kind kind,
162
+ std::optional<ActorIsolation> actorIsolation,
163
+ NominalTypeDecl *actorInstanceType = nullptr )
164
+ : kind(kind), actorIsolation(actorIsolation),
165
+ actorInstanceType (actorInstanceType) {}
166
+
167
+ public:
168
+ ValueIsolationRegionInfo () : kind(Kind::Unknown), actorIsolation() {}
169
+
170
+ operator bool () const { return kind != Kind::Unknown; }
171
+
172
+ operator Kind () const { return kind; }
173
+
174
+ Kind getKind () const { return kind; }
175
+
176
+ bool isDisconnected () const { return kind == Kind::Disconnected; }
177
+ bool isActorIsolated () const { return kind == Kind::Actor; }
178
+
179
+ void print (llvm::raw_ostream &os) const {
180
+ switch (Kind (*this )) {
181
+ case Unknown:
182
+ os << " unknown" ;
183
+ return ;
184
+ case Disconnected:
185
+ os << " disconnected" ;
186
+ return ;
187
+ case Actor:
188
+ os << " actor" ;
189
+ return ;
190
+ }
191
+ }
192
+
193
+ SWIFT_DEBUG_DUMP {
194
+ print (llvm::dbgs ());
195
+ llvm::dbgs () << ' \n ' ;
196
+ }
197
+
198
+ std::optional<ActorIsolation> getActorIsolation () const {
199
+ assert (!actorInstanceType &&
200
+ " Should never be set if getActorIsolation is called" );
201
+ return actorIsolation;
202
+ }
203
+
204
+ NominalTypeDecl *getActorInstance () const {
205
+ assert (!actorIsolation.has_value ());
206
+ return actorInstanceType;
207
+ }
208
+
209
+ [[nodiscard]] ValueIsolationRegionInfo
210
+ merge (ValueIsolationRegionInfo other) const {
211
+ // If we are greater than the other kind, then we are further along the
212
+ // lattice. We ignore the change.
213
+ if (unsigned (other.kind ) < unsigned (kind))
214
+ return *this ;
215
+
216
+ assert (kind != ValueIsolationRegionInfo::Actor &&
217
+ " Actor should never be merged with another actor?!" );
218
+
219
+ // Otherwise, take the other value.
220
+ return other;
221
+ }
222
+
223
+ ValueIsolationRegionInfo withActorIsolated (ActorIsolation isolation) {
224
+ return ValueIsolationRegionInfo::getActorIsolated (isolation);
225
+ }
226
+
227
+ static ValueIsolationRegionInfo getDisconnected () {
228
+ return {Kind::Disconnected, {}};
229
+ }
230
+
231
+ static ValueIsolationRegionInfo
232
+ getActorIsolated (ActorIsolation actorIsolation) {
233
+ return {Kind::Actor, actorIsolation};
234
+ }
235
+
236
+ // / Sometimes we may have something that is actor isolated or that comes from
237
+ // / a type. First try getActorIsolation and otherwise, just use the type.
238
+ static ValueIsolationRegionInfo getActorIsolated (NominalTypeDecl *nomDecl) {
239
+ auto actorIsolation = swift::getActorIsolation (nomDecl);
240
+ if (actorIsolation.isActorIsolated ())
241
+ return getActorIsolated (actorIsolation);
242
+ if (nomDecl->isActor ())
243
+ return {Kind::Actor, {}, nomDecl};
244
+ return {};
245
+ }
246
+ };
247
+
141
248
} // namespace regionanalysisimpl
142
249
143
250
class regionanalysisimpl ::TrackableValueState {
144
251
unsigned id;
145
252
TrackedValueFlagSet flagSet = {TrackableValueFlag::isMayAlias};
253
+ ValueIsolationRegionInfo regionInfo =
254
+ ValueIsolationRegionInfo::getDisconnected ();
146
255
147
256
public:
148
257
TrackableValueState (unsigned newID) : id(newID) {}
@@ -159,10 +268,20 @@ class regionanalysisimpl::TrackableValueState {
159
268
160
269
bool isNonSendable () const { return !isSendable (); }
161
270
162
- bool isActorDerived () const {
163
- return flagSet. contains (TrackableValueFlag::isActorDerived );
271
+ ValueIsolationRegionInfo::Kind getRegionInfoKind () {
272
+ return regionInfo. getKind ( );
164
273
}
165
274
275
+ ActorIsolation getActorIsolation () const {
276
+ return regionInfo.getActorIsolation ().value ();
277
+ }
278
+
279
+ void mergeIsolationRegionInfo (ValueIsolationRegionInfo newRegionInfo) {
280
+ regionInfo = regionInfo.merge (newRegionInfo);
281
+ }
282
+
283
+ ValueIsolationRegionInfo getIsolationRegionInfo () const { return regionInfo; }
284
+
166
285
TrackableValueID getID () const { return TrackableValueID (id); }
167
286
168
287
void addFlag (TrackableValueFlag flag) { flagSet |= flag; }
@@ -173,7 +292,9 @@ class regionanalysisimpl::TrackableValueState {
173
292
os << " TrackableValueState[id: " << id
174
293
<< " ][is_no_alias: " << (isNoAlias () ? " yes" : " no" )
175
294
<< " ][is_sendable: " << (isSendable () ? " yes" : " no" )
176
- << " ][is_actor_derived: " << (isActorDerived () ? " yes" : " no" ) << " ]." ;
295
+ << " ][region_value_kind: " ;
296
+ getIsolationRegionInfo ().print (os);
297
+ os << " ]." ;
177
298
}
178
299
179
300
SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
@@ -257,7 +378,9 @@ class regionanalysisimpl::TrackableValue {
257
378
258
379
bool isNonSendable () const { return !isSendable (); }
259
380
260
- bool isActorDerived () const { return valueState.isActorDerived (); }
381
+ ValueIsolationRegionInfo getIsolationRegionInfo () const {
382
+ return valueState.getIsolationRegionInfo ();
383
+ }
261
384
262
385
TrackableValueID getID () const {
263
386
return TrackableValueID (valueState.getID ());
@@ -293,6 +416,7 @@ class RegionAnalysisValueMap {
293
416
using TrackableValueState = regionanalysisimpl::TrackableValueState;
294
417
using TrackableValueID = Element;
295
418
using RepresentativeValue = regionanalysisimpl::RepresentativeValue;
419
+ using ValueIsolationRegionInfo = regionanalysisimpl::ValueIsolationRegionInfo;
296
420
297
421
private:
298
422
// / A map from the representative of an equivalence class of values to their
@@ -326,7 +450,7 @@ class RegionAnalysisValueMap {
326
450
// / value" returns an empty SILValue.
327
451
SILValue maybeGetRepresentative (Element trackableValueID) const ;
328
452
329
- bool isActorDerived (Element trackableValueID) const ;
453
+ ValueIsolationRegionInfo getIsolationRegion (Element trackableValueID) const ;
330
454
331
455
ArrayRef<Element> getNonTransferrableElements () const {
332
456
return neverTransferredValueIDs;
@@ -345,8 +469,10 @@ class RegionAnalysisValueMap {
345
469
std::optional<TrackableValue> getValueForId (TrackableValueID id) const ;
346
470
std::optional<TrackableValue> tryToTrackValue (SILValue value) const ;
347
471
TrackableValue
348
- getActorIntroducingRepresentative (SILInstruction *introducingInst) const ;
349
- bool markValueAsActorDerived (SILValue value);
472
+ getActorIntroducingRepresentative (SILInstruction *introducingInst,
473
+ ValueIsolationRegionInfo isolation) const ;
474
+ bool mergeIsolationRegionInfo (SILValue value,
475
+ ValueIsolationRegionInfo isolation);
350
476
void addNeverTransferredValueID (TrackableValueID valueID) {
351
477
neverTransferredValueIDs.push_back (valueID);
352
478
}
0 commit comments