Skip to content

Commit 5ffdfb9

Browse files
authored
Merge pull request swiftlang#77600 from rjmccall/simplify-constructor-concurrency-prolog-emission
Use common code paths for constructor concurrency prologs
2 parents 4190411 + e99ec88 commit 5ffdfb9

File tree

4 files changed

+28
-48
lines changed

4 files changed

+28
-48
lines changed

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -226,37 +226,32 @@ void SILGenFunction::emitExpectedExecutorProlog() {
226226
}
227227
}
228228

229-
void SILGenFunction::emitConstructorPrologActorHop(
230-
SILLocation loc, std::optional<ActorIsolation> maybeIso) {
231-
loc = loc.asAutoGenerated();
232-
233-
SILValue executorForInitialHop;
234-
235-
if (maybeIso) {
236-
// If the constructor is isolated to `self`, this must be an actor
237-
// constructor. Lazily emit the ExpectedExecutor reference so that
238-
// DI can lower it appropriately.
239-
if (maybeIso->getKind() == ActorIsolation::ActorInstance &&
240-
maybeIso->getActorInstance() ==
241-
cast<ConstructorDecl>(F.getDeclRef().getDecl())
242-
->getImplicitSelfDecl()) {
229+
void SILGenFunction::emitConstructorExpectedExecutorProlog() {
230+
auto ctor = cast<ConstructorDecl>(F.getDeclRef().getDecl());
231+
232+
// In async actor initializers that are isolated to self, we need
233+
// to emit the ExpectedExecutor reference lazily.
234+
if (ctor->hasAsync()) {
235+
auto isolation = getActorIsolation(ctor);
236+
auto selfDecl = ctor->getImplicitSelfDecl();
237+
238+
if (isolation.getKind() == ActorIsolation::ActorInstance &&
239+
isolation.getActorInstance() == selfDecl) {
243240
assert(isCtorWithHopsInjectedByDefiniteInit());
244241
ExpectedExecutor.setLazy();
245-
executorForInitialHop = emitGenericExecutor(loc);
246242

247-
// Otherwise, emit the executor normally.
248-
} else if (auto executor = emitExecutor(loc, *maybeIso, std::nullopt)) {
249-
executorForInitialHop = *executor;
250-
ExpectedExecutor.set(executorForInitialHop);
251-
}
252-
}
243+
auto loc = SILLocation(selfDecl);
244+
loc.markAsPrologue();
245+
loc = loc.asAutoGenerated();
253246

254-
if (!ExpectedExecutor.isValid()) {
255-
executorForInitialHop = emitGenericExecutor(loc);
256-
ExpectedExecutor.set(executorForInitialHop);
247+
auto initialExecutor = emitGenericExecutor(loc);
248+
B.createHopToExecutor(loc, initialExecutor, /*mandatory*/ false);
249+
return;
250+
}
257251
}
258252

259-
B.createHopToExecutor(loc, executorForInitialHop, /*mandatory*/ false);
253+
// Otherwise, emit the normal expected executor prolog.
254+
emitExpectedExecutorProlog();
260255
}
261256

262257
void SILGenFunction::emitPrologGlobalActorHop(SILLocation loc,

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -673,12 +673,7 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
673673
AllocatorMetatype = emitConstructorMetatypeArg(*this, ctor);
674674

675675
// Make sure we've hopped to the right global actor, if any.
676-
if (ctor->hasAsync()) {
677-
auto isolation = getActorIsolation(ctor);
678-
SILLocation prologueLoc(selfDecl);
679-
prologueLoc.markAsPrologue();
680-
emitConstructorPrologActorHop(prologueLoc, isolation);
681-
}
676+
emitConstructorExpectedExecutorProlog();
682677

683678
// Create a basic block to jump to for the implicit 'self' return.
684679
// We won't emit this until after we've emitted the body.
@@ -1134,12 +1129,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
11341129
selfClassDecl->isDistributedActor() && !isDelegating;
11351130

11361131
// Make sure we've hopped to the right global actor, if any.
1137-
if (ctor->hasAsync()) {
1138-
auto isolation = getActorIsolation(ctor);
1139-
SILLocation prologueLoc(selfDecl);
1140-
prologueLoc.markAsPrologue();
1141-
emitConstructorPrologActorHop(prologueLoc, isolation);
1142-
}
1132+
emitConstructorExpectedExecutorProlog();
11431133

11441134
if (!NeedsBoxForSelf) {
11451135
SILLocation PrologueLoc(selfDecl);

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,17 +1201,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
12011201
/// that unsafely inherits its executor.
12021202
bool unsafelyInheritsExecutor();
12031203

1204-
/// A version of `emitHopToTargetActor` that is specialized to the needs
1205-
/// of various types of ConstructorDecls, like class or value initializers,
1206-
/// because their prolog emission is not the same as for regular functions.
1207-
///
1208-
/// This function emits the appropriate hop_to_executor for a constructor's
1209-
/// prologue.
1210-
///
1211-
/// NOTE: this does not support actor initializers!
1212-
void emitConstructorPrologActorHop(SILLocation loc,
1213-
std::optional<ActorIsolation> actorIso);
1214-
12151204
/// Set the given global actor as the isolation for this function
12161205
/// (generally a thunk) and hop to it.
12171206
void emitPrologGlobalActorHop(SILLocation loc, Type globalActor);
@@ -1322,6 +1311,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
13221311
/// Set up the ExpectedExecutor field for the current function and emit
13231312
/// whatever hops or assertions are locally expected.
13241313
void emitExpectedExecutorProlog();
1314+
void emitConstructorExpectedExecutorProlog();
13251315

13261316
/// Create SILArguments in the entry block that bind a single value
13271317
/// of the given parameter suitably for being forwarded.

test/Concurrency/isolated_parameters.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,8 @@ public actor MyActorIsolatedParameterMerge {
585585
}
586586
}
587587
}
588+
589+
// rdar://138394497
590+
class ClassWithIsolatedAsyncInitializer {
591+
init(isolation: isolated (any Actor)? = #isolation) async {}
592+
}

0 commit comments

Comments
 (0)