Skip to content

Commit 0977c0a

Browse files
committed
ensure that async initializers for reference and value
types correctly hop to the right global-actor in their prolog.
1 parent 4f6eb85 commit 0977c0a

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

lib/SILGen/SILGenConstructor.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "ArgumentSource.h"
1414
#include "Conversion.h"
15+
#include "ExecutorBreadcrumb.h"
1516
#include "Initialization.h"
1617
#include "LValue.h"
1718
#include "RValue.h"
@@ -357,6 +358,13 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
357358
ctor->getThrowsLoc());
358359
emitConstructorMetatypeArg(*this, ctor);
359360

361+
// Make sure we've hopped to the right global actor, if any.
362+
if (ctor->hasAsync()) {
363+
SILLocation prologueLoc(selfDecl);
364+
prologueLoc.markAsPrologue();
365+
emitConstructorPrologActorHop(prologueLoc, getActorIsolation(ctor));
366+
}
367+
360368
// Create a basic block to jump to for the implicit 'self' return.
361369
// We won't emit this until after we've emitted the body.
362370
// The epilog takes a void return because the return of 'self' is implicit.
@@ -662,6 +670,18 @@ static void emitDefaultActorInitialization(SILGenFunction &SGF,
662670
{ self.borrow(SGF, loc).getValue() });
663671
}
664672

673+
void SILGenFunction::emitConstructorPrologActorHop(
674+
SILLocation loc,
675+
Optional<ActorIsolation> maybeIso) {
676+
if (!maybeIso)
677+
return;
678+
679+
if (auto executor = emitExecutor(loc, *maybeIso, None)) {
680+
ExpectedExecutor = *executor;
681+
B.createHopToExecutor(loc, *executor);
682+
}
683+
}
684+
665685
void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
666686
MagicFunctionName = SILGenModule::getMagicFunctionName(ctor);
667687

@@ -724,6 +744,13 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
724744
SILType selfTy = getLoweredLoadableType(selfDecl->getType());
725745
ManagedValue selfArg = B.createInputFunctionArgument(selfTy, selfDecl);
726746

747+
// Make sure we've hopped to the right global actor, if any.
748+
if (ctor->hasAsync() && !selfClassDecl->isActor()) {
749+
SILLocation prologueLoc(selfDecl);
750+
prologueLoc.markAsPrologue();
751+
emitConstructorPrologActorHop(prologueLoc, getActorIsolation(ctor));
752+
}
753+
727754
if (!NeedsBoxForSelf) {
728755
SILLocation PrologueLoc(selfDecl);
729756
PrologueLoc.markAsPrologue();

lib/SILGen/SILGenFunction.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,17 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
839839
Optional<ActorIsolation> actorIso,
840840
Optional<ManagedValue> actorSelf);
841841

842+
/// A version of `emitHopToTargetActor` that is specialized to the needs
843+
/// of various types of ConstructorDecls, like class or value initializers,
844+
/// because their prolog emission is not the same as for regular functions.
845+
///
846+
/// This function emits the appropriate hop_to_executor for a constructor's
847+
/// prologue.
848+
///
849+
/// NOTE: this does not support actor initializers!
850+
void emitConstructorPrologActorHop(SILLocation loc,
851+
Optional<ActorIsolation> actorIso);
852+
842853
/// Emit the executor for the given actor isolation.
843854
Optional<SILValue> emitExecutor(SILLocation loc,
844855
ActorIsolation isolation,

0 commit comments

Comments
 (0)