@@ -546,6 +546,10 @@ class Callee {
546
546
return cast<EnumElementDecl>(Constant.getDecl ());
547
547
}
548
548
549
+ ValueDecl *getDecl () {
550
+ return Constant.getDecl ();
551
+ }
552
+
549
553
CalleeTypeInfo createCalleeTypeInfo (SILGenFunction &SGF,
550
554
Optional<SILDeclRef> constant,
551
555
SILType formalFnType) const & {
@@ -3646,14 +3650,16 @@ class CallEmission {
3646
3650
Callee callee;
3647
3651
FormalEvaluationScope initialWritebackScope;
3648
3652
unsigned expectedSiteCount;
3653
+ bool implicitlyAsync;
3649
3654
3650
3655
public:
3651
3656
// / Create an emission for a call of the given callee.
3652
3657
CallEmission (SILGenFunction &SGF, Callee &&callee,
3653
3658
FormalEvaluationScope &&writebackScope)
3654
3659
: SGF(SGF), callee(std::move(callee)),
3655
3660
initialWritebackScope (std::move(writebackScope)),
3656
- expectedSiteCount(callee.getParameterListCount()) {}
3661
+ expectedSiteCount(callee.getParameterListCount()),
3662
+ implicitlyAsync(false ) {}
3657
3663
3658
3664
// / A factory method for decomposing the apply expr \p e into a call
3659
3665
// / emission.
@@ -3688,6 +3694,11 @@ class CallEmission {
3688
3694
return (callee.kind == Callee::Kind::EnumElement);
3689
3695
}
3690
3696
3697
+ // / Sets a flag that indicates whether this call be treated as being
3698
+ // / implicitly async, i.e., it requires a hop_to_executor prior to
3699
+ // / invoking the sync callee, etc.
3700
+ void setImplicitlyAsync (bool flag) { implicitlyAsync = flag; }
3701
+
3691
3702
CleanupHandle applyCoroutine (SmallVectorImpl<ManagedValue> &yields);
3692
3703
3693
3704
RValue apply (SGFContext C = SGFContext()) {
@@ -3912,11 +3923,15 @@ RValue CallEmission::applyNormalCall(SGFContext C) {
3912
3923
3913
3924
auto mv = callee.getFnValue (SGF, borrowedSelf);
3914
3925
3926
+ Optional<ValueDecl*> calleeDeclInfo;
3927
+ if (implicitlyAsync)
3928
+ calleeDeclInfo = callee.getDecl ();
3929
+
3915
3930
// Emit the uncurried call.
3916
3931
return SGF.emitApply (
3917
3932
std::move (resultPlan), std::move (argScope), uncurriedLoc.getValue (), mv,
3918
3933
callee.getSubstitutions (), uncurriedArgs, calleeTypeInfo, options,
3919
- uncurriedContext);
3934
+ uncurriedContext, calleeDeclInfo );
3920
3935
}
3921
3936
3922
3937
static void emitPseudoFunctionArguments (SILGenFunction &SGF,
@@ -4224,6 +4239,8 @@ CallEmission CallEmission::forApplyExpr(SILGenFunction &SGF, ApplyExpr *e) {
4224
4239
4225
4240
emission.addCallSite (apply.callSite , std::move (preparedArgs),
4226
4241
apply.callSite ->throws ());
4242
+
4243
+ emission.setImplicitlyAsync (apply.callSite ->implicitlyAsync ());
4227
4244
}
4228
4245
4229
4246
return emission;
@@ -4266,6 +4283,31 @@ bool SILGenModule::isNonMutatingSelfIndirect(SILDeclRef methodRef) {
4266
4283
return self.isFormalIndirect ();
4267
4284
}
4268
4285
4286
+ Optional<SILValue> SILGenFunction::EmitLoadActorExecutorForCallee (
4287
+ SILGenFunction *SGF,
4288
+ ValueDecl *calleeVD,
4289
+ ArrayRef<ManagedValue> args) {
4290
+ if (auto *funcDecl = dyn_cast_or_null<AbstractFunctionDecl>(calleeVD)) {
4291
+ auto actorIso = getActorIsolation (funcDecl);
4292
+ switch (actorIso.getKind ()) {
4293
+ case ActorIsolation::Unspecified:
4294
+ case ActorIsolation::Independent:
4295
+ case ActorIsolation::IndependentUnsafe:
4296
+ break ;
4297
+
4298
+ case ActorIsolation::ActorInstance: {
4299
+ assert (args.size () > 0 && " no self argument for actor-instance call?" );
4300
+ auto calleeSelf = args.back ();
4301
+ return calleeSelf.borrow (*SGF, SGF->F .getLocation ()).getValue ();
4302
+ }
4303
+
4304
+ case ActorIsolation::GlobalActor:
4305
+ return SGF->emitLoadGlobalActorExecutor (actorIso.getGlobalActor ());
4306
+ }
4307
+ }
4308
+ return None;
4309
+ }
4310
+
4269
4311
// ===----------------------------------------------------------------------===//
4270
4312
// Top Level Entrypoints
4271
4313
// ===----------------------------------------------------------------------===//
@@ -4279,7 +4321,8 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
4279
4321
ManagedValue fn, SubstitutionMap subs,
4280
4322
ArrayRef<ManagedValue> args,
4281
4323
const CalleeTypeInfo &calleeTypeInfo,
4282
- ApplyOptions options, SGFContext evalContext) {
4324
+ ApplyOptions options, SGFContext evalContext,
4325
+ Optional<ValueDecl *> implicitlyAsyncApply) {
4283
4326
auto substFnType = calleeTypeInfo.substFnType ;
4284
4327
auto substResultType = calleeTypeInfo.substResultType ;
4285
4328
@@ -4365,15 +4408,31 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
4365
4408
subs.getGenericSignature ().getCanonicalSignature ());
4366
4409
}
4367
4410
4368
- auto rawDirectResult = [&] {
4411
+ // The presence of `implicitlyAsyncApply` indicates that the callee is a
4412
+ // synchronous function isolated to an actor other than our own.
4413
+ // Such functions require the caller to hop to the callee's executor
4414
+ // prior to invoking the callee.
4415
+ if (implicitlyAsyncApply.hasValue ()) {
4416
+ assert (F.isAsync () && " cannot hop_to_executor in a non-async func!" );
4417
+
4418
+ auto calleeVD = implicitlyAsyncApply.getValue ();
4419
+ auto maybeExecutor = EmitLoadActorExecutorForCallee (this , calleeVD, args);
4420
+
4421
+ assert (maybeExecutor.hasValue ());
4422
+ B.createHopToExecutor (loc, maybeExecutor.getValue ());
4423
+ }
4424
+
4425
+ SILValue rawDirectResult;
4426
+ {
4369
4427
SmallVector<SILValue, 1 > rawDirectResults;
4370
4428
emitRawApply (*this , loc, fn, subs, args, substFnType, options,
4371
4429
indirectResultAddrs, rawDirectResults);
4372
4430
assert (rawDirectResults.size () == 1 );
4373
- return rawDirectResults[0 ];
4374
- }();
4431
+ rawDirectResult = rawDirectResults[0 ];
4432
+ }
4375
4433
4376
- if (substFnType->isAsync ())
4434
+ // hop back to the current executor
4435
+ if (substFnType->isAsync () || implicitlyAsyncApply.hasValue ())
4377
4436
emitHopToCurrentExecutor (loc);
4378
4437
4379
4438
// Pop the argument scope.
@@ -4482,7 +4541,7 @@ RValue SILGenFunction::emitMonomorphicApply(
4482
4541
*this , calleeTypeInfo, loc, evalContext);
4483
4542
ArgumentScope argScope (*this , loc);
4484
4543
return emitApply (std::move (resultPlan), std::move (argScope), loc, fn, {},
4485
- args, calleeTypeInfo, options, evalContext);
4544
+ args, calleeTypeInfo, options, evalContext, None );
4486
4545
}
4487
4546
4488
4547
// / Emit either an 'apply' or a 'try_apply', with the error branch of
@@ -4768,7 +4827,7 @@ SILGenFunction::emitApplyOfLibraryIntrinsic(SILLocation loc,
4768
4827
ResultPlanBuilder::computeResultPlan (*this , calleeTypeInfo, loc, ctx);
4769
4828
ArgumentScope argScope (*this , loc);
4770
4829
return emitApply (std::move (resultPlan), std::move (argScope), loc, mv, subMap,
4771
- finalArgs, calleeTypeInfo, ApplyOptions::None, ctx);
4830
+ finalArgs, calleeTypeInfo, ApplyOptions::None, ctx, None );
4772
4831
}
4773
4832
4774
4833
StringRef SILGenFunction::getMagicFunctionString () {
0 commit comments