Skip to content

Commit f1a0665

Browse files
committed
[Distributed] move SILGen for destructor resignIdentity to
SILGenDistributed
1 parent aaf8137 commit f1a0665

File tree

2 files changed

+109
-109
lines changed

2 files changed

+109
-109
lines changed

lib/SILGen/SILGenDestructor.cpp

Lines changed: 3 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
7676
resultSelfValue = selfValue;
7777
}
7878

79-
79+
/// A distributed actor resigns its identity as it is deallocated.
80+
/// This way the transport knows it must not deliver any more messages to it,
81+
/// and can remove it from its (weak) lookup tables.
8082
if (cd->isDistributedActor()) {
8183
SILBasicBlock *continueBB = createBasicBlock();
8284
injectDistributedActorDestructorLifecycleCall(dd, selfValue, continueBB);
@@ -109,113 +111,6 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
109111
B.createReturn(returnLoc, resultSelfValue);
110112
}
111113

112-
void SILGenFunction::injectDistributedActorDestructorLifecycleCall(
113-
DestructorDecl *dd, SILValue selfValue, SILBasicBlock *continueBB) {
114-
ASTContext &ctx = getASTContext();
115-
116-
auto cd = cast<ClassDecl>(dd->getDeclContext());
117-
assert(cd->isDistributedActor() &&
118-
"only distributed actors have transport lifecycle hooks in deinit");
119-
120-
RegularLocation Loc(dd);
121-
if (dd->isImplicit())
122-
Loc.markAutoGenerated();
123-
124-
auto selfDecl = dd->getImplicitSelfDecl();
125-
auto selfManagedValue = ManagedValue::forUnmanaged(selfValue);
126-
auto selfType = selfDecl->getType();
127-
128-
// ==== locate: self.id
129-
auto idVarDeclRefs = cd->lookupDirect(ctx.Id_id);
130-
assert(idVarDeclRefs.size() == 1);
131-
auto *idVarDeclRef = dyn_cast<VarDecl>(idVarDeclRefs.front());
132-
assert(idVarDeclRef);
133-
auto idRef =
134-
B.createRefElementAddr(Loc, selfValue, idVarDeclRef,
135-
getLoweredType(idVarDeclRef->getType()));
136-
137-
// ==== locate: self.actorTransport
138-
auto transportVarDeclRefs = cd->lookupDirect(ctx.Id_actorTransport);
139-
assert(transportVarDeclRefs.size() == 1);
140-
auto *transportVarDeclRef = dyn_cast<VarDecl>(transportVarDeclRefs.front());
141-
auto transportRef =
142-
B.createRefElementAddr(Loc, selfValue, transportVarDeclRef,
143-
getLoweredType(transportVarDeclRef->getType()));
144-
145-
// locate: self.transport.resignIdentity(...)
146-
auto *transportDecl = ctx.getActorTransportDecl();
147-
auto resignFnDecls = transportDecl->lookupDirect(ctx.Id_resignIdentity);
148-
assert(resignFnDecls.size() == 1);
149-
auto *resignFnDecl = resignFnDecls.front();
150-
auto resignFnRef = SILDeclRef(resignFnDecl);
151-
152-
// we only transport.resignIdentity if we are a local actor,
153-
// and thus the address was created by transport.assignIdentity.
154-
auto isRemoteBB = createBasicBlock();
155-
auto isLocalBB = createBasicBlock();
156-
157-
// if __isRemoteActor(self) {
158-
// ...
159-
// } else {
160-
// ...
161-
// }
162-
{
163-
FuncDecl *isRemoteFn = ctx.getIsRemoteDistributedActor();
164-
assert(isRemoteFn && "Could not find 'is remote' function, is the "
165-
"'_Distributed' module available?");
166-
167-
ManagedValue selfAnyObject =
168-
B.createInitExistentialRef(Loc, getLoweredType(ctx.getAnyObjectType()),
169-
CanType(selfType), selfManagedValue, {});
170-
auto result = emitApplyOfLibraryIntrinsic(
171-
Loc, isRemoteFn, SubstitutionMap(), {selfAnyObject}, SGFContext());
172-
173-
SILValue isRemoteResult =
174-
std::move(result).forwardAsSingleValue(*this, Loc);
175-
SILValue isRemoteResultUnwrapped =
176-
emitUnwrapIntegerResult(Loc, isRemoteResult);
177-
178-
B.createCondBranch(Loc, isRemoteResultUnwrapped, isRemoteBB, isLocalBB);
179-
}
180-
181-
// if remote
182-
// === <noop>
183-
{
184-
B.emitBlock(isRemoteBB);
185-
// noop, remote actors don't do anything in their deinit
186-
B.createBranch(Loc, continueBB);
187-
}
188-
189-
// if local
190-
// === self.transport.resignIdentity(self.address)
191-
{
192-
B.emitBlock(isLocalBB);
193-
194-
auto openedTransport =
195-
OpenedArchetypeType::get(transportVarDeclRef->getType());
196-
auto transportAddr = B.createOpenExistentialAddr(
197-
Loc, /*operand=*/transportRef, getLoweredType(openedTransport),
198-
OpenedExistentialAccess::Immutable);
199-
200-
auto resignFnType = SGM.M.Types.getConstantFunctionType(
201-
TypeExpansionContext::minimal(), resignFnRef);
202-
203-
auto witness = B.createWitnessMethod(
204-
Loc, openedTransport, ProtocolConformanceRef(transportDecl),
205-
resignFnRef, SILType::getPrimitiveObjectType(resignFnType));
206-
207-
auto subs = SubstitutionMap::getProtocolSubstitutions(
208-
transportDecl, openedTransport, ProtocolConformanceRef(transportDecl));
209-
210-
SmallVector<SILValue, 2> params;
211-
params.push_back(idRef);
212-
params.push_back(transportAddr); // self for the call, as last param
213-
214-
B.createApply(Loc, witness, subs, params);
215-
B.createBranch(Loc, continueBB);
216-
}
217-
}
218-
219114
void SILGenFunction::emitDeallocatingDestructor(DestructorDecl *dd) {
220115
MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit"));
221116

lib/SILGen/SILGenDistributed.cpp

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,113 @@ void SILGenFunction::emitDistributedActorFactory(FuncDecl *fd) {
576576
/******************* DISTRIBUTED DEINIT: resignAddress ************************/
577577
/******************************************************************************/
578578

579-
// TODO: implement calling resignAddress via a defer in deinit
580579

580+
void SILGenFunction::injectDistributedActorDestructorLifecycleCall(
581+
DestructorDecl *dd, SILValue selfValue, SILBasicBlock *continueBB) {
582+
ASTContext &ctx = getASTContext();
583+
584+
auto cd = cast<ClassDecl>(dd->getDeclContext());
585+
assert(cd->isDistributedActor() &&
586+
"only distributed actors have transport lifecycle hooks in deinit");
587+
588+
RegularLocation Loc(dd);
589+
if (dd->isImplicit())
590+
Loc.markAutoGenerated();
591+
592+
auto selfDecl = dd->getImplicitSelfDecl();
593+
auto selfManagedValue = ManagedValue::forUnmanaged(selfValue);
594+
auto selfType = selfDecl->getType();
595+
596+
// ==== locate: self.id
597+
auto idVarDeclRefs = cd->lookupDirect(ctx.Id_id);
598+
assert(idVarDeclRefs.size() == 1);
599+
auto *idVarDeclRef = dyn_cast<VarDecl>(idVarDeclRefs.front());
600+
assert(idVarDeclRef);
601+
auto idRef =
602+
B.createRefElementAddr(Loc, selfValue, idVarDeclRef,
603+
getLoweredType(idVarDeclRef->getType()));
604+
605+
// ==== locate: self.actorTransport
606+
auto transportVarDeclRefs = cd->lookupDirect(ctx.Id_actorTransport);
607+
assert(transportVarDeclRefs.size() == 1);
608+
auto *transportVarDeclRef = dyn_cast<VarDecl>(transportVarDeclRefs.front());
609+
auto transportRef =
610+
B.createRefElementAddr(Loc, selfValue, transportVarDeclRef,
611+
getLoweredType(transportVarDeclRef->getType()));
612+
613+
// locate: self.transport.resignIdentity(...)
614+
auto *transportDecl = ctx.getActorTransportDecl();
615+
auto resignFnDecls = transportDecl->lookupDirect(ctx.Id_resignIdentity);
616+
assert(resignFnDecls.size() == 1);
617+
auto *resignFnDecl = resignFnDecls.front();
618+
auto resignFnRef = SILDeclRef(resignFnDecl);
619+
620+
// we only transport.resignIdentity if we are a local actor,
621+
// and thus the address was created by transport.assignIdentity.
622+
auto isRemoteBB = createBasicBlock();
623+
auto isLocalBB = createBasicBlock();
624+
625+
// if __isRemoteActor(self) {
626+
// ...
627+
// } else {
628+
// ...
629+
// }
630+
{
631+
FuncDecl *isRemoteFn = ctx.getIsRemoteDistributedActor();
632+
assert(isRemoteFn && "Could not find 'is remote' function, is the "
633+
"'_Distributed' module available?");
634+
635+
ManagedValue selfAnyObject =
636+
B.createInitExistentialRef(Loc, getLoweredType(ctx.getAnyObjectType()),
637+
CanType(selfType), selfManagedValue, {});
638+
auto result = emitApplyOfLibraryIntrinsic(
639+
Loc, isRemoteFn, SubstitutionMap(), {selfAnyObject}, SGFContext());
640+
641+
SILValue isRemoteResult =
642+
std::move(result).forwardAsSingleValue(*this, Loc);
643+
SILValue isRemoteResultUnwrapped =
644+
emitUnwrapIntegerResult(Loc, isRemoteResult);
645+
646+
B.createCondBranch(Loc, isRemoteResultUnwrapped, isRemoteBB, isLocalBB);
647+
}
648+
649+
// if remote
650+
// === <noop>
651+
{
652+
B.emitBlock(isRemoteBB);
653+
// noop, remote actors don't do anything in their deinit
654+
B.createBranch(Loc, continueBB);
655+
}
656+
657+
// if local
658+
// === self.transport.resignIdentity(self.address)
659+
{
660+
B.emitBlock(isLocalBB);
661+
662+
auto openedTransport =
663+
OpenedArchetypeType::get(transportVarDeclRef->getType());
664+
auto transportAddr = B.createOpenExistentialAddr(
665+
Loc, /*operand=*/transportRef, getLoweredType(openedTransport),
666+
OpenedExistentialAccess::Immutable);
667+
668+
auto resignFnType = SGM.M.Types.getConstantFunctionType(
669+
TypeExpansionContext::minimal(), resignFnRef);
670+
671+
auto witness = B.createWitnessMethod(
672+
Loc, openedTransport, ProtocolConformanceRef(transportDecl),
673+
resignFnRef, SILType::getPrimitiveObjectType(resignFnType));
674+
675+
auto subs = SubstitutionMap::getProtocolSubstitutions(
676+
transportDecl, openedTransport, ProtocolConformanceRef(transportDecl));
677+
678+
SmallVector<SILValue, 2> params;
679+
params.push_back(idRef);
680+
params.push_back(transportAddr); // self for the call, as last param
681+
682+
B.createApply(Loc, witness, subs, params);
683+
B.createBranch(Loc, continueBB);
684+
}
685+
}
581686

582687
/******************************************************************************/
583688
/***************************** DISTRIBUTED THUNKS *****************************/

0 commit comments

Comments
 (0)