Skip to content

Commit 6c0cfac

Browse files
committed
remove dependence on system parameter in SILGen/DefiniteInit
1 parent 01a5faf commit 6c0cfac

File tree

5 files changed

+118
-54
lines changed

5 files changed

+118
-54
lines changed

include/swift/SILOptimizer/Utils/DistributedActor.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ class SILLocation;
3232
class SILType;
3333
class SILValue;
3434

35-
/// Finds the first `DistributedActorSystem`-compatible parameter of the given function.
36-
/// \returns nullptr if the function does not have such a parameter.
37-
SILArgument *findFirstDistributedActorSystemArg(SILFunction &F);
38-
3935
/// Emit a call to a witness of the DistributedActorSystem protocol.
4036
///
4137
/// \param methodName The name of the method on the DistributedActorSystem protocol.

lib/SILGen/SILGenConstructor.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
835835
}
836836
}
837837

838-
// Distributed actor initializers implicitly initialize their transport and id
838+
// Some distributed actor initializers need to init the actorSystem & id now
839839
if (isDesignatedDistActorInit) {
840840
emitDistributedActorImplicitPropertyInits(ctor, selfArg);
841841
}
@@ -1257,4 +1257,3 @@ void SILGenFunction::emitIVarInitializer(SILDeclRef ivarInitializer) {
12571257

12581258
emitEpilog(loc);
12591259
}
1260-

lib/SILGen/SILGenDistributed.cpp

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,56 @@ static void emitDistributedIfRemoteBranch(SILGenFunction &SGF, SILLocation Loc,
133133
// ==== ------------------------------------------------------------------------
134134
// MARK: local instance initialization
135135

136+
static SILArgument *findFirstDistributedActorSystemArg(SILFunction &F) {
137+
auto *module = F.getModule().getSwiftModule();
138+
auto &C = F.getASTContext();
139+
140+
auto *transportProto = C.getProtocol(KnownProtocolKind::DistributedActorSystem);
141+
Type transportTy = transportProto->getDeclaredInterfaceType();
142+
143+
for (auto arg : F.getArguments()) {
144+
// TODO(distributed): also be able to locate a generic transport
145+
Type argTy = arg->getType().getASTType();
146+
auto argDecl = arg->getDecl();
147+
148+
auto conformsToTransport =
149+
module->lookupConformance(argDecl->getInterfaceType(), transportProto);
150+
151+
// Is it a protocol that conforms to DistributedActorSystem?
152+
if (argTy->isEqual(transportTy) || conformsToTransport) {
153+
return arg;
154+
}
155+
156+
// Is it some specific DistributedActorSystem?
157+
auto result = module->lookupConformance(argTy, transportProto);
158+
if (!result.isInvalid()) {
159+
return arg;
160+
}
161+
}
162+
163+
#ifndef NDEBUG
164+
llvm_unreachable("Missing required DistributedActorSystem argument!");
165+
#endif
166+
167+
return nullptr;
168+
}
169+
136170
/// For the initialization of a local distributed actor instance, emits code to
137171
/// initialize the instance's stored property corresponding to the system.
138172
static void emitActorSystemInit(SILGenFunction &SGF,
139173
ConstructorDecl *ctor,
140174
SILLocation loc,
141175
ManagedValue actorSelf) {
176+
assert(ctor->isImplicit() && "unexpected explicit dist actor init");
177+
assert(ctor->isDesignatedInit());
178+
142179
auto *dc = ctor->getDeclContext();
143180
auto classDecl = dc->getSelfClassDecl();
144181
auto &C = ctor->getASTContext();
145182

146-
// Sema has already guaranteed that there is exactly one DistributedActorSystem
147-
// argument to the constructor, so we grab the first one from the params.
183+
// By construction, automatically generated distributed actor ctors have
184+
// exactly one ActorSystem-conforming argument to the constructor,
185+
// so we grab the first one from the params.
148186
SILValue systemArg = findFirstDistributedActorSystemArg(SGF.F);
149187
VarDecl *var = lookupProperty(classDecl, C.Id_actorSystem);
150188
assert(var);
@@ -160,6 +198,9 @@ static void emitActorSystemInit(SILGenFunction &SGF,
160198
/// \endverbatim
161199
static void emitIDInit(SILGenFunction &SGF, ConstructorDecl *ctor,
162200
SILLocation loc, ManagedValue borrowedSelfArg) {
201+
assert(ctor->isImplicit() && "unexpected explicit dist actor init");
202+
assert(ctor->isDesignatedInit());
203+
163204
auto &C = ctor->getASTContext();
164205
auto &B = SGF.B;
165206
auto &F = SGF.F;
@@ -173,7 +214,8 @@ static void emitIDInit(SILGenFunction &SGF, ConstructorDecl *ctor,
173214
auto selfMetatype = SGF.getLoweredType(MetatypeType::get(selfTy));
174215
SILValue selfMetatypeValue = B.createMetatype(loc, selfMetatype);
175216

176-
SILValue actorSystem = findFirstDistributedActorSystemArg(F);
217+
// since we're doing this only for the implicitly defined ctors, grab from arg
218+
SILValue actorSystem = findFirstDistributedActorSystemArg(SGF.F);
177219

178220
// --- create a temporary storage for the result of the call
179221
// it will be deallocated automatically as we exit this scope
@@ -230,12 +272,19 @@ void SILGenFunction::emitDistributedActorImplicitPropertyInits(
230272
loc.markAutoGenerated();
231273

232274
selfArg = selfArg.borrow(*this, loc);
233-
emitActorSystemInit(*this, ctor, loc, selfArg);
234-
emitIDInit(*this, ctor, loc, selfArg);
235275

236276
// register a clean-up to resign the identity upon abnormal exit
277+
// we do this regardless of initializer kind, since it's easy to do in SILGen.
237278
auto *actorDecl = cast<ClassDecl>(ctor->getParent()->getAsDecl());
238279
Cleanups.pushCleanup<ResignIdentity>(actorDecl, selfArg.getValue());
280+
281+
// Users must initialize the actorSystem property explicitly in their ctors
282+
if (!ctor->isImplicit())
283+
return;
284+
285+
// implicit ctors initialize these from the ActorSystem parameter.
286+
emitActorSystemInit(*this, ctor, loc, selfArg);
287+
emitIDInit(*this, ctor, loc, selfArg);
239288
}
240289

241290
void SILGenFunction::emitDistributedActorReady(
@@ -244,12 +293,27 @@ void SILGenFunction::emitDistributedActorReady(
244293
// Only designated initializers get the lifecycle handling injected
245294
assert(ctor->isDesignatedInit());
246295

247-
SILValue transport = findFirstDistributedActorSystemArg(F);
296+
auto &C = ctor->getASTContext();
297+
auto *dc = ctor->getDeclContext();
298+
auto classDecl = dc->getSelfClassDecl();
248299

249300
FullExpr scope(Cleanups, CleanupLocation(loc));
250301
auto borrowedSelf = actorSelf.borrow(*this, loc);
251302

252-
emitActorReadyCall(B, loc, borrowedSelf.getValue(), transport);
303+
// --- load the actor system from the actor instance
304+
ManagedValue actorSystem;
305+
SGFContext sgfCxt; // TODO: is this right?
306+
{
307+
VarDecl *property = lookupProperty(classDecl, C.Id_actorSystem);
308+
Type formalType = F.mapTypeIntoContext(property->getInterfaceType());
309+
SILType loweredType = getLoweredType(formalType).getAddressType();
310+
SILValue actorSystemRef = emitActorPropertyReference(
311+
*this, loc, borrowedSelf.getValue(), property);
312+
actorSystem = emitLoad(loc, actorSystemRef,
313+
getTypeLowering(loweredType), sgfCxt, IsNotTake);
314+
}
315+
316+
emitActorReadyCall(B, loc, borrowedSelf.getValue(), actorSystem.getValue());
253317
}
254318

255319
// ==== ------------------------------------------------------------------------

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,42 @@ static bool isDistributedActorCtor(SILFunction &F) {
787787
return false;
788788
}
789789

790+
//static SILValue emitActorPropertyReference(
791+
// SILGenFunction &SGF, SILLocation loc, SILValue actorSelf,
792+
// VarDecl *property) {
793+
// Type formalType = SGF.F.mapTypeIntoContext(property->getInterfaceType());
794+
// SILType loweredType = SGF.getLoweredType(formalType).getAddressType();
795+
// return SGF.B.createRefElementAddr(loc, actorSelf, property, loweredType);
796+
//}
797+
798+
/// Creates a reference to the distributed actor's \p actorSystem
799+
/// stored property.
800+
static SILValue refDistributedActorSystem(SILLocation loc,
801+
SILBuilder &b,
802+
SILValue actorInstance,
803+
SILFunction &F) {
804+
ClassDecl *clsDecl = F.getDeclContext()->getSelfClassDecl();
805+
assert(clsDecl->isDistributedActor());
806+
807+
// get the VarDecl corresponding to the actorSystem.
808+
auto refs = clsDecl->lookupDirect(clsDecl->getASTContext().Id_actorSystem);
809+
assert(refs.size() == 1);
810+
VarDecl *actorSystemVar = dyn_cast<VarDecl>(refs.front());
811+
812+
return b.createRefElementAddr(loc, actorInstance, actorSystemVar);
813+
}
814+
815+
static void loadCopyWithCleanups(SILLocation loc, SILBuilder& b, SILValue ref,
816+
llvm::function_ref<void(SILValue)> scope) {
817+
auto copy = b.createLoad(loc, ref, LoadOwnershipQualifier::Copy);
818+
auto borrow = b.createBeginBorrow(loc, copy);
819+
820+
scope(borrow);
821+
822+
b.createEndBorrow(loc, borrow);
823+
b.createDestroyValue(loc, copy);
824+
}
825+
790826
/// Injects a hop_to_executor instruction after the specified insertion point.
791827
static void injectHopToExecutorAfter(SILLocation loc,
792828
SILBasicBlock::iterator insertPt,
@@ -806,29 +842,32 @@ static void injectHopToExecutorAfter(SILLocation loc,
806842
LLVM_DEBUG(llvm::dbgs() << "hop-injector: injecting after " << *insertPt);
807843
SILBuilderWithScope::insertAfter(insertPt, [&](SILBuilder &b) {
808844

845+
SILLocation genLoc = loc.asAutoGenerated();
809846
const bool delegating = !TheMemory.isNonDelegatingInit();
810847
SILValue val = TheMemory.getUninitializedValue();
811848

812849
// delegating inits always have an alloc we need to load it from.
813850
if (delegating)
814-
val = b.createLoad(loc.asAutoGenerated(), val,
815-
LoadOwnershipQualifier::Copy);
851+
val = b.createLoad(genLoc, val, LoadOwnershipQualifier::Copy);
816852

817-
SILValue actor = b.createBeginBorrow(loc.asAutoGenerated(), val);
853+
SILValue actor = b.createBeginBorrow(genLoc, val);
818854

819855
b.createHopToExecutor(loc.asAutoGenerated(), actor, /*mandatory=*/false);
820856

821857
// Distributed actors also need to notify their transport immediately
822858
// after performing the hop.
823859
if (!delegating && isDistributedActorCtor(b.getFunction())) {
824-
auto transport = findFirstDistributedActorSystemArg(b.getFunction());
825-
emitActorReadyCall(b, loc.asAutoGenerated(), actor, transport);
860+
SILValue systemRef = refDistributedActorSystem(loc.asAutoGenerated(),
861+
b, actor, b.getFunction());
862+
loadCopyWithCleanups(genLoc, b, systemRef, [&](SILValue systemVal) {
863+
emitActorReadyCall(b, genLoc, actor, systemVal);
864+
});
826865
}
827866

828-
b.createEndBorrow(loc.asAutoGenerated(), actor);
867+
b.createEndBorrow(genLoc, actor);
829868

830869
if (delegating)
831-
b.createDestroyValue(loc.asAutoGenerated(), val);
870+
b.createDestroyValue(genLoc, val);
832871
});
833872
};
834873

lib/SILOptimizer/Utils/DistributedActor.cpp

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,40 +18,6 @@
1818

1919
namespace swift {
2020

21-
SILArgument *findFirstDistributedActorSystemArg(SILFunction &F) {
22-
auto *module = F.getModule().getSwiftModule();
23-
auto &C = F.getASTContext();
24-
25-
auto *transportProto = C.getProtocol(KnownProtocolKind::DistributedActorSystem);
26-
Type transportTy = transportProto->getDeclaredInterfaceType();
27-
28-
for (auto arg : F.getArguments()) {
29-
// TODO(distributed): also be able to locate a generic transport
30-
Type argTy = arg->getType().getASTType();
31-
auto argDecl = arg->getDecl();
32-
33-
auto conformsToTransport =
34-
module->lookupConformance(argDecl->getInterfaceType(), transportProto);
35-
36-
// Is it a protocol that conforms to DistributedActorSystem?
37-
if (argTy->isEqual(transportTy) || conformsToTransport) {
38-
return arg;
39-
}
40-
41-
// Is it some specific DistributedActorSystem?
42-
auto result = module->lookupConformance(argTy, transportProto);
43-
if (!result.isInvalid()) {
44-
return arg;
45-
}
46-
}
47-
48-
#ifndef NDEBUG
49-
llvm_unreachable("Missing required DistributedActorSystem argument!");
50-
#endif
51-
52-
return nullptr;
53-
}
54-
5521
void emitDistributedActorSystemWitnessCall(
5622
SILBuilder &B, SILLocation loc, DeclName methodName,
5723
SILValue base,

0 commit comments

Comments
 (0)