Skip to content

Commit 38e6303

Browse files
committed
fixed emission of actorReady call in init epilogue
1 parent 006e2b4 commit 38e6303

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

lib/SILGen/SILGenConstructor.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,10 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
742742

743743
SILType selfTy = getLoweredLoadableType(selfDecl->getType());
744744
ManagedValue selfArg = B.createInputFunctionArgument(selfTy, selfDecl);
745+
746+
// is this a designated initializer for a distributed actor?
747+
const bool isDesignatedDistActorInit =
748+
selfClassDecl->isDistributedActor() && !isDelegating;
745749

746750
// Make sure we've hopped to the right global actor, if any.
747751
if (ctor->hasAsync() && !selfClassDecl->isActor()) {
@@ -780,7 +784,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
780784
}
781785

782786
// Distributed actor initializers implicitly initialize their transport and id
783-
if (selfClassDecl->isDistributedActor() && !isDelegating) {
787+
if (isDesignatedDistActorInit) {
784788
initializeDistributedActorImplicitStorageInit(ctor, selfArg);
785789
}
786790

@@ -814,6 +818,13 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
814818
failureExitBB = createBasicBlock();
815819
failureExitArg = failureExitBB->createPhiArgument(
816820
resultLowering.getLoweredType(), OwnershipKind::Owned);
821+
822+
// For an async distributed actor init, we must `resignIdentity` before
823+
// the clean-ups are triggered in this failure block.
824+
if (isDesignatedDistActorInit && ctor->hasAsync()) {
825+
// TODO: refactor emitDistributedActor_resignAddress so we can call it
826+
// within this initializer.
827+
}
817828

818829
Cleanups.emitCleanupsForReturn(ctor, IsForUnwind);
819830
SILValue nilResult =
@@ -865,6 +876,18 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
865876
B.clearInsertionPoint();
866877
}
867878
}
879+
880+
// For distributed actors, their synchronous initializers invoke "actor ready"
881+
// at the very end, just before returning on a successful initialization.
882+
// There is no need for injecting `resignIdentity` calls in such inits,
883+
// because we can never call `actorReady` prematurely.
884+
if (isDesignatedDistActorInit && !ctor->hasAsync()) {
885+
RegularLocation loc(ctor);
886+
loc.markAutoGenerated();
887+
888+
SILGenSavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
889+
emitDistributedActorReady(loc, ctor, selfArg);
890+
}
868891

869892
CleanupStateRestorationScope SelfCleanupSave(Cleanups);
870893

@@ -931,12 +954,6 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
931954
// Unpop our selfArg cleanup, so we can forward.
932955
std::move(SelfCleanupSave).pop();
933956

934-
// TODO(distributed): rdar://81783599 if this is a distributed actor, jump to the distributedReady block?
935-
// // For distributed actors, emit "actor ready" since we successfully initialized
936-
// if (selfClassDecl->isDistributedActor() && !isDelegating) {
937-
// emitDistributedActorReady(ctor, selfArg);
938-
// }
939-
940957
// Finish off the epilog by returning. If this is a failable ctor, then we
941958
// actually jump to the failure epilog to keep the invariant that there is
942959
// only one SIL return instruction per SIL function.

lib/SILGen/SILGenDistributed.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -388,22 +388,21 @@ void SILGenFunction::initializeDistributedActorImplicitStorageInit(
388388
}
389389

390390
void SILGenFunction::emitDistributedActorReady(
391-
ConstructorDecl *ctor, ManagedValue selfArg) {
391+
SILLocation loc, ConstructorDecl *ctor, ManagedValue actorSelf) {
392392

393393
auto *dc = ctor->getDeclContext();
394394
auto classDecl = dc->getSelfClassDecl();
395395
auto &C = classDecl->getASTContext();
396396

397397
// Only designated initializers get the lifecycle handling injected
398-
if (!ctor->isDesignatedInit())
399-
return;
400-
401-
SILLocation loc = RegularLocation(ctor);
402-
loc.markAutoGenerated();
398+
assert(ctor->isDesignatedInit());
399+
400+
// setup scope for clean-ups
401+
FullExpr scope(Cleanups, CleanupLocation(loc));
403402

404403
// === Prepare the arguments
405404
SILValue transportArgValue = getActorTransportArgument(C, F, ctor);
406-
SILValue selfArgValue = F.getSelfArgument();
405+
actorSelf = actorSelf.borrow(*this, loc);
407406

408407
ProtocolDecl *distributedActorProto = C.getProtocol(KnownProtocolKind::DistributedActor);
409408
ProtocolDecl *transportProto = C.getProtocol(KnownProtocolKind::ActorTransport);
@@ -466,7 +465,7 @@ void SILGenFunction::emitDistributedActorReady(
466465
// ---- actually call transport.actorReady(self)
467466
B.createApply(
468467
loc, readyWitnessMethod, subs,
469-
{ selfArgValue, transportValue});
468+
{ actorSelf.getValue(), transportValue});
470469
}
471470

472471
/******************************************************************************/

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2020,7 +2020,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
20202020
/// Notify transport that actor has initialized successfully,
20212021
/// and is ready to receive messages.
20222022
void emitDistributedActorReady(
2023-
ConstructorDecl *ctor, ManagedValue selfArg);
2023+
SILLocation loc, ConstructorDecl *ctor, ManagedValue actorSelf);
20242024

20252025
/// Inject distributed actor and transport interaction code into the destructor.
20262026
void emitDistributedActor_resignAddress(

0 commit comments

Comments
 (0)