1414#include " ArgumentSource.h"
1515#include " Callee.h"
1616#include " Conversion.h"
17+ #include " ExecutorBreadcrumb.h"
1718#include " FormalEvaluation.h"
1819#include " Initialization.h"
1920#include " LValue.h"
@@ -1707,7 +1708,8 @@ static void emitRawApply(SILGenFunction &SGF,
17071708 CanSILFunctionType substFnType,
17081709 ApplyOptions options,
17091710 ArrayRef<SILValue> indirectResultAddrs,
1710- SmallVectorImpl<SILValue> &rawResults) {
1711+ SmallVectorImpl<SILValue> &rawResults,
1712+ ExecutorBreadcrumb prevExecutor) {
17111713 SILFunctionConventions substFnConv (substFnType, SGF.SGM .M );
17121714 // Get the callee value.
17131715 bool isConsumed = substFnType->isCalleeConsumed ();
@@ -1783,7 +1785,7 @@ static void emitRawApply(SILGenFunction &SGF,
17831785 rawResults.push_back (result);
17841786
17851787 SILBasicBlock *errorBB =
1786- SGF.getTryApplyErrorDest (loc, substFnType,
1788+ SGF.getTryApplyErrorDest (loc, substFnType, prevExecutor,
17871789 substFnType->getErrorResult (),
17881790 options.contains (ApplyFlags::DoesNotThrow));
17891791
@@ -3815,7 +3817,7 @@ SILGenFunction::emitBeginApply(SILLocation loc, ManagedValue fn,
38153817 // Emit the call.
38163818 SmallVector<SILValue, 4 > rawResults;
38173819 emitRawApply (*this , loc, fn, subs, args, substFnType, options,
3818- /* indirect results*/ {}, rawResults);
3820+ /* indirect results*/ {}, rawResults, ExecutorBreadcrumb () );
38193821
38203822 auto token = rawResults.pop_back_val ();
38213823 auto yieldValues = llvm::makeArrayRef (rawResults);
@@ -4385,6 +4387,8 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
43854387 subs.getGenericSignature ().getCanonicalSignature ());
43864388 }
43874389
4390+ ExecutorBreadcrumb breadcrumb;
4391+
43884392 // The presence of `implicitlyAsyncApply` indicates that the callee is a
43894393 // synchronous function isolated to an actor other than our own.
43904394 // Such functions require the caller to hop to the callee's executor
@@ -4399,24 +4403,28 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
43994403 if (args.size () > 0 )
44004404 actorSelf = args.back ();
44014405
4402- auto didHop = emitHopToTargetActor (loc, getActorIsolation (funcDecl),
4403- actorSelf);
4404- assert (didHop);
4406+ breadcrumb = emitHopToTargetActor (loc, getActorIsolation (funcDecl),
4407+ actorSelf);
44054408 }
4409+ } else if (actor && substFnType->isAsync ()) {
4410+ // Otherwise, if we're in an actor method ourselves, and we're calling into
4411+ // any sort of async function, we'll want to make sure to hop back to our
4412+ // own executor afterward, since the callee could have made arbitrary hops
4413+ // out of our isolation domain.
4414+ breadcrumb = ExecutorBreadcrumb (actor);
44064415 }
44074416
44084417 SILValue rawDirectResult;
44094418 {
44104419 SmallVector<SILValue, 1 > rawDirectResults;
44114420 emitRawApply (*this , loc, fn, subs, args, substFnType, options,
4412- indirectResultAddrs, rawDirectResults);
4421+ indirectResultAddrs, rawDirectResults, breadcrumb );
44134422 assert (rawDirectResults.size () == 1 );
44144423 rawDirectResult = rawDirectResults[0 ];
44154424 }
44164425
44174426 // hop back to the current executor
4418- if (substFnType->isAsync () || implicitlyAsyncApply.hasValue ())
4419- emitHopToCurrentExecutor (loc);
4427+ breadcrumb.emit (*this , loc);
44204428
44214429 // Pop the argument scope.
44224430 argScope.pop ();
0 commit comments