@@ -125,24 +125,133 @@ enum class TrackableValueFlag {
125125
126126 // / Set to true if this TrackableValue's representative is Sendable.
127127 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 ,
137128};
138129
139130using TrackedValueFlagSet = OptionSet<TrackableValueFlag>;
140131
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+
141248} // namespace regionanalysisimpl
142249
143250class regionanalysisimpl ::TrackableValueState {
144251 unsigned id;
145252 TrackedValueFlagSet flagSet = {TrackableValueFlag::isMayAlias};
253+ ValueIsolationRegionInfo regionInfo =
254+ ValueIsolationRegionInfo::getDisconnected ();
146255
147256public:
148257 TrackableValueState (unsigned newID) : id(newID) {}
@@ -159,10 +268,20 @@ class regionanalysisimpl::TrackableValueState {
159268
160269 bool isNonSendable () const { return !isSendable (); }
161270
162- bool isActorDerived () const {
163- return flagSet. contains (TrackableValueFlag::isActorDerived );
271+ ValueIsolationRegionInfo::Kind getRegionInfoKind () {
272+ return regionInfo. getKind ( );
164273 }
165274
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+
166285 TrackableValueID getID () const { return TrackableValueID (id); }
167286
168287 void addFlag (TrackableValueFlag flag) { flagSet |= flag; }
@@ -173,7 +292,9 @@ class regionanalysisimpl::TrackableValueState {
173292 os << " TrackableValueState[id: " << id
174293 << " ][is_no_alias: " << (isNoAlias () ? " yes" : " no" )
175294 << " ][is_sendable: " << (isSendable () ? " yes" : " no" )
176- << " ][is_actor_derived: " << (isActorDerived () ? " yes" : " no" ) << " ]." ;
295+ << " ][region_value_kind: " ;
296+ getIsolationRegionInfo ().print (os);
297+ os << " ]." ;
177298 }
178299
179300 SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
@@ -257,7 +378,9 @@ class regionanalysisimpl::TrackableValue {
257378
258379 bool isNonSendable () const { return !isSendable (); }
259380
260- bool isActorDerived () const { return valueState.isActorDerived (); }
381+ ValueIsolationRegionInfo getIsolationRegionInfo () const {
382+ return valueState.getIsolationRegionInfo ();
383+ }
261384
262385 TrackableValueID getID () const {
263386 return TrackableValueID (valueState.getID ());
@@ -293,6 +416,7 @@ class RegionAnalysisValueMap {
293416 using TrackableValueState = regionanalysisimpl::TrackableValueState;
294417 using TrackableValueID = Element;
295418 using RepresentativeValue = regionanalysisimpl::RepresentativeValue;
419+ using ValueIsolationRegionInfo = regionanalysisimpl::ValueIsolationRegionInfo;
296420
297421private:
298422 // / A map from the representative of an equivalence class of values to their
@@ -326,7 +450,7 @@ class RegionAnalysisValueMap {
326450 // / value" returns an empty SILValue.
327451 SILValue maybeGetRepresentative (Element trackableValueID) const ;
328452
329- bool isActorDerived (Element trackableValueID) const ;
453+ ValueIsolationRegionInfo getIsolationRegion (Element trackableValueID) const ;
330454
331455 ArrayRef<Element> getNonTransferrableElements () const {
332456 return neverTransferredValueIDs;
@@ -345,8 +469,10 @@ class RegionAnalysisValueMap {
345469 std::optional<TrackableValue> getValueForId (TrackableValueID id) const ;
346470 std::optional<TrackableValue> tryToTrackValue (SILValue value) const ;
347471 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);
350476 void addNeverTransferredValueID (TrackableValueID valueID) {
351477 neverTransferredValueIDs.push_back (valueID);
352478 }
0 commit comments