@@ -197,110 +197,64 @@ void SILGenFunction::emitIVarDestroyer(SILDeclRef ivarDestroyer) {
197
197
emitEpilog (loc);
198
198
}
199
199
200
+ void SILGenFunction::destroyClassMember (SILLocation cleanupLoc,
201
+ ManagedValue selfValue, VarDecl *D) {
202
+ const TypeLowering &ti = getTypeLowering (D->getType ());
203
+ if (!ti.isTrivial ()) {
204
+ SILValue addr =
205
+ B.createRefElementAddr (cleanupLoc, selfValue.getValue (), D,
206
+ ti.getLoweredType ().getAddressType ());
207
+ addr = B.createBeginAccess (
208
+ cleanupLoc, addr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
209
+ false /* noNestedConflict*/ , false /* fromBuiltin*/ );
210
+ B.createDestroyAddr (cleanupLoc, addr);
211
+ B.createEndAccess (cleanupLoc, addr, false /* is aborting*/ );
212
+ }
213
+ }
214
+
200
215
void SILGenFunction::emitClassMemberDestruction (ManagedValue selfValue,
201
216
ClassDecl *cd,
202
217
CleanupLocation cleanupLoc) {
203
218
assert (selfValue.getOwnershipKind () == OwnershipKind::Guaranteed);
204
- ASTContext &ctx = getASTContext ();
205
-
206
- auto loc = SILLocation (cd);
207
- loc.markAutoGenerated ();
208
219
220
+ // / If this ClassDecl is a distributed actor, we must synthesise another code
221
+ // / path for deallocating a 'remote' actor. In that case, these basic blocks
222
+ // / are used to return to the "normal" (i.e. 'local' instance) destruction.
223
+ // /
224
+ // / For other cases, the basic blocks are not necessary and the destructor
225
+ // / can just emit all the normal destruction code right into the current block.
226
+ // If set, used as the basic block for the destroying of all members.
209
227
SILBasicBlock* normalMemberDestroyBB = nullptr ;
210
- SILBasicBlock* returnBB = nullptr ;
211
-
212
- auto destroyVar = [&](VarDecl *vd) {
213
- const TypeLowering &ti = getTypeLowering (vd->getType ());
214
- if (!ti.isTrivial ()) {
215
- SILValue addr =
216
- B.createRefElementAddr (cleanupLoc, selfValue.getValue (), vd,
217
- ti.getLoweredType ().getAddressType ());
218
- addr = B.createBeginAccess (
219
- cleanupLoc, addr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
220
- false /* noNestedConflict*/ , false /* fromBuiltin*/ );
221
- B.createDestroyAddr (cleanupLoc, addr);
222
- B.createEndAccess (cleanupLoc, addr, false /* is aborting*/ );
223
- }
224
- };
228
+ // If set, used as the basic block after members have been destroyed,
229
+ // and we're ready to perform final cleanups before returning.
230
+ SILBasicBlock* finishBB = nullptr ;
225
231
232
+ // / A distributed actor may be 'remote' in which case there is no need to
233
+ // / destroy "all" members, because they never had storage to begin with.
226
234
if (cd->isDistributedActor ()) {
227
- auto selfTy = cd->getDeclaredInterfaceType ();
228
-
229
- Scope scope (Cleanups, CleanupLocation (loc));
230
-
231
- auto isLocalBB = createBasicBlock ();
235
+ finishBB = createBasicBlock ();
232
236
normalMemberDestroyBB = createBasicBlock ();
233
- auto remoteMemberDestroyBB = createBasicBlock ();
234
- returnBB = createBasicBlock ();
235
-
236
- // TODO(distributed): de-duplicate with the thunk logic in SILGenDistributed
237
- // if __isRemoteActor(self) {
238
- // ...
239
- // } else {
240
- // ...
241
- // }
242
- {
243
- FuncDecl *isRemoteFn = ctx.getIsRemoteDistributedActor ();
244
- assert (isRemoteFn && " Could not find 'is remote' function, is the "
245
- " '_Distributed' module available?" );
246
-
247
- ManagedValue selfAnyObject =
248
- B.createInitExistentialRef (loc, getLoweredType (ctx.getAnyObjectType ()),
249
- CanType (selfTy), selfValue, {});
250
- auto result = emitApplyOfLibraryIntrinsic (
251
- loc, isRemoteFn, SubstitutionMap (), {selfAnyObject}, SGFContext ());
252
-
253
- SILValue isRemoteResult =
254
- std::move (result).forwardAsSingleValue (*this , loc);
255
- SILValue isRemoteResultUnwrapped =
256
- emitUnwrapIntegerResult (loc, isRemoteResult);
257
-
258
- B.createCondBranch (loc, isRemoteResultUnwrapped, remoteMemberDestroyBB, isLocalBB);
259
- }
260
237
261
- // // if __isRemoteActor(self)
262
- // {
263
- // // destroy only self.id and self.actorTransport
264
- // }
265
- {
266
- B.emitBlock (remoteMemberDestroyBB);
267
-
268
- for (VarDecl *vd : cd->getStoredProperties ()) {
269
- if (!vd->getAttrs ().hasAttribute <DistributedActorIndependentAttr>())
270
- continue ;
271
-
272
- destroyVar (vd);
273
- }
274
-
275
- B.createBranch (loc, returnBB);
276
- }
277
-
278
- // // else (local distributed actor)
279
- // {
280
- // <continue normal deinit>
281
- // }
282
- {
283
- B.emitBlock (isLocalBB);
284
-
285
- B.createBranch (loc, normalMemberDestroyBB);
286
- }
238
+ emitDistributedActorClassMemberDestruction (cleanupLoc, selfValue, cd,
239
+ normalMemberDestroyBB,
240
+ finishBB);
287
241
}
288
242
243
+ // / Destroy all members.
289
244
{
290
245
if (normalMemberDestroyBB)
291
246
B.emitBlock (normalMemberDestroyBB);
292
247
293
248
for (VarDecl *vd : cd->getStoredProperties ())
294
- destroyVar ( vd);
249
+ destroyClassMember (cleanupLoc, selfValue, vd);
295
250
296
- if (returnBB )
297
- B.createBranch (loc, returnBB );
251
+ if (finishBB )
252
+ B.createBranch (cleanupLoc, finishBB );
298
253
}
299
254
300
255
{
301
- if (returnBB)
302
- B.emitBlock (returnBB);
303
-
256
+ if (finishBB)
257
+ B.emitBlock (finishBB);
304
258
305
259
if (cd->isRootDefaultActor ()) {
306
260
// TODO(distributed): we may need to call the distributed destroy here instead?
0 commit comments