@@ -31,15 +31,60 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
31
31
Loc.markAutoGenerated ();
32
32
33
33
auto cd = cast<ClassDecl>(dd->getDeclContext ());
34
+ auto &C = cd->getASTContext ();
34
35
SILValue selfValue = emitSelfDecl (dd->getImplicitSelfDecl ());
35
36
36
37
// Create a basic block to jump to for the implicit destruction behavior
37
38
// of releasing the elements and calling the superclass destructor.
38
39
// We won't actually emit the block until we finish with the destructor body.
39
40
prepareEpilog (None, false , CleanupLocation (Loc));
40
41
42
+ auto cleanupLoc = CleanupLocation (Loc);
43
+
44
+ SILBasicBlock *deinitBodyBB = nullptr ;
45
+ SILBasicBlock *finishBB = nullptr ;
46
+ if (cd->isDistributedActor ()) {
47
+ auto remoteBB = createBasicBlock (" remoteActorDeinitBB" );
48
+ finishBB = createBasicBlock (" finishDeinitBB" );
49
+ deinitBodyBB = createBasicBlock (" deinitBodyBB" );
50
+
51
+ // FIXME: what should the type of management be for this?
52
+ auto managedSelf = ManagedValue::forBorrowedRValue (selfValue);
53
+
54
+ auto selfTy = F.mapTypeIntoContext (cd->getDeclaredInterfaceType ());
55
+ emitDistributedIfRemoteBranch (
56
+ SILLocation (Loc),
57
+ managedSelf, selfTy,
58
+ /* if remote=*/ remoteBB,
59
+ /* if local=*/ deinitBodyBB);
60
+
61
+ {
62
+ B.emitBlock (remoteBB);
63
+
64
+ // Note that we do NOT execute user-declared the deinit body.
65
+ // They would be free to access state which does not exist in a remote DA
66
+
67
+ // we are a remote instance,
68
+ // the only properties we can destroy are the id and system properties.
69
+ for (VarDecl *vd : cd->getStoredProperties ()) {
70
+ if (getActorIsolation (vd) == ActorIsolation::ActorInstance)
71
+ continue ;
72
+
73
+ // Just to double-check, we only want to destroy `id` and `actorSystem`
74
+ if (vd->getBaseIdentifier () == C.Id_id ||
75
+ vd->getBaseIdentifier () == C.Id_actorSystem ) {
76
+ destroyClassMember (cleanupLoc, managedSelf, vd);
77
+ }
78
+ }
79
+
80
+ B.createBranch (SILLocation (Loc), finishBB);
81
+ }
82
+ }
83
+
41
84
emitProfilerIncrement (dd->getTypecheckedBody ());
42
85
// Emit the destructor body.
86
+ if (deinitBodyBB)
87
+ B.emitBlock (deinitBodyBB);
43
88
emitStmt (dd->getTypecheckedBody ());
44
89
45
90
Optional<SILValue> maybeReturnValue;
@@ -49,8 +94,6 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
49
94
if (!maybeReturnValue)
50
95
return ;
51
96
52
- auto cleanupLoc = CleanupLocation (Loc);
53
-
54
97
// If we have a superclass, invoke its destructor.
55
98
SILValue resultSelfValue;
56
99
SILType objectPtrTy = SILType::getNativeObjectType (F.getASTContext ());
@@ -78,22 +121,6 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
78
121
resultSelfValue = selfValue;
79
122
}
80
123
81
- // / A distributed actor resigns its identity as it is deallocated.
82
- // / This way the transport knows it must not deliver any more messages to it,
83
- // / and can remove it from its (weak) lookup tables.
84
- if (cd->isDistributedActor ()) {
85
- SILBasicBlock *continueBB = createBasicBlock ();
86
-
87
- RegularLocation loc (dd);
88
- if (dd->isImplicit ())
89
- loc.markAutoGenerated ();
90
-
91
- // FIXME: what should the type of management be for this?
92
- auto managedSelf = ManagedValue::forBorrowedRValue (selfValue);
93
- emitConditionalResignIdentityCall (loc, cd, managedSelf, continueBB);
94
- B.emitBlock (continueBB);
95
- }
96
-
97
124
ArgumentScope S (*this , Loc);
98
125
ManagedValue borrowedValue =
99
126
ManagedValue::forUnmanaged (resultSelfValue).borrow (*this , cleanupLoc);
@@ -103,8 +130,18 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
103
130
B.createUncheckedRefCast (cleanupLoc, borrowedValue, classTy);
104
131
}
105
132
133
+ // A distributed actor must invoke `actorSystem.resignID` as it deinits.
134
+ if (cd->isDistributedActor ()) {
135
+ // This must only be called by a *local* distributed actor (not a remote proxy).
136
+ // Since this call is emitted after the user-declared body of the deinit,
137
+ // just before returning; this is guaranteed to only be executed in the local
138
+ // actor case - because the body is never executed for a remote proxy either.
139
+ emitDistributedActorSystemResignIDCall (
140
+ cleanupLoc, cd, ManagedValue::forBorrowedRValue (selfValue));
141
+ }
142
+
106
143
// Release our members.
107
- emitClassMemberDestruction (borrowedValue, cd, cleanupLoc);
144
+ emitClassMemberDestruction (borrowedValue, cd, cleanupLoc, finishBB );
108
145
109
146
S.pop ();
110
147
@@ -199,7 +236,7 @@ void SILGenFunction::emitIVarDestroyer(SILDeclRef ivarDestroyer) {
199
236
cleanupLoc, selfValue.forward (*this ), OwnershipKind::Guaranteed);
200
237
selfValue = emitManagedBorrowedRValueWithCleanup (guaranteedSelf);
201
238
}
202
- emitClassMemberDestruction (selfValue, cd, cleanupLoc);
239
+ emitClassMemberDestruction (selfValue, cd, cleanupLoc, /* finishBB= */ nullptr );
203
240
}
204
241
205
242
B.createReturn (loc, emitEmptyTuple (loc));
@@ -359,32 +396,10 @@ void SILGenFunction::emitRecursiveChainDestruction(ManagedValue selfValue,
359
396
360
397
void SILGenFunction::emitClassMemberDestruction (ManagedValue selfValue,
361
398
ClassDecl *cd,
362
- CleanupLocation cleanupLoc) {
399
+ CleanupLocation cleanupLoc,
400
+ SILBasicBlock *finishBB) {
363
401
assert (selfValue.getOwnershipKind () == OwnershipKind::Guaranteed);
364
402
365
- // / If this ClassDecl is a distributed actor, we must synthesise another code
366
- // / path for deallocating a 'remote' actor. In that case, these basic blocks
367
- // / are used to return to the "normal" (i.e. 'local' instance) destruction.
368
- // /
369
- // / For other cases, the basic blocks are not necessary and the destructor
370
- // / can just emit all the normal destruction code right into the current block.
371
- // If set, used as the basic block for the destroying of all members.
372
- SILBasicBlock *normalMemberDestroyBB = nullptr ;
373
- // If set, used as the basic block after members have been destroyed,
374
- // and we're ready to perform final cleanups before returning.
375
- SILBasicBlock *finishBB = nullptr ;
376
-
377
- // / A distributed actor may be 'remote' in which case there is no need to
378
- // / destroy "all" members, because they never had storage to begin with.
379
- if (cd->isDistributedActor ()) {
380
- finishBB = createBasicBlock ();
381
- normalMemberDestroyBB = createBasicBlock ();
382
-
383
- emitDistributedActorClassMemberDestruction (cleanupLoc, selfValue, cd,
384
- normalMemberDestroyBB,
385
- finishBB);
386
- }
387
-
388
403
// Before we destroy all fields, we check if any of them are
389
404
// recursively the same type as `self`, so we can iteratively
390
405
// deinitialize them, to prevent deep recursion and potential
@@ -395,9 +410,6 @@ void SILGenFunction::emitClassMemberDestruction(ManagedValue selfValue,
395
410
396
411
// / Destroy all members.
397
412
{
398
- if (normalMemberDestroyBB)
399
- B.emitBlock (normalMemberDestroyBB);
400
-
401
413
for (VarDecl *vd : cd->getStoredProperties ()) {
402
414
if (recursiveLinks.contains (vd))
403
415
continue ;
0 commit comments