Skip to content

Commit bc8bd4e

Browse files
committed
Emit actor hop as part of call to the getter.
When emitting a call to the getter for storage, emit the actor hop (and hop back) as part of the call itself, rather than around the whole initialization. This address a bug involving initialization with an optional binding in an `if let`, where the hop-back would only be performed on the non-nil branch. Fixes rdar://96487805 / FB10562197
1 parent 791a1bd commit bc8bd4e

File tree

4 files changed

+86
-92
lines changed

4 files changed

+86
-92
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5805,13 +5805,15 @@ SILDeclRef SILGenModule::getAccessorDeclRef(AccessorDecl *accessor) {
58055805
}
58065806

58075807
/// Emit a call to a getter.
5808-
RValue SILGenFunction::emitGetAccessor(SILLocation loc, SILDeclRef get,
5809-
SubstitutionMap substitutions,
5810-
ArgumentSource &&selfValue, bool isSuper,
5811-
bool isDirectUse,
5812-
PreparedArguments &&subscriptIndices,
5813-
SGFContext c,
5814-
bool isOnSelfParameter) {
5808+
RValue SILGenFunction::emitGetAccessor(
5809+
SILLocation loc, SILDeclRef get,
5810+
SubstitutionMap substitutions,
5811+
ArgumentSource &&selfValue, bool isSuper,
5812+
bool isDirectUse,
5813+
PreparedArguments &&subscriptIndices,
5814+
SGFContext c,
5815+
bool isOnSelfParameter,
5816+
Optional<ImplicitActorHopTarget> implicitActorHopTarget) {
58155817
// Scope any further writeback just within this operation.
58165818
FormalEvaluationScope writebackScope(*this);
58175819

@@ -5822,6 +5824,9 @@ RValue SILGenFunction::emitGetAccessor(SILLocation loc, SILDeclRef get,
58225824
CanAnyFunctionType accessType = getter.getSubstFormalType();
58235825

58245826
CallEmission emission(*this, std::move(getter), std::move(writebackScope));
5827+
if (implicitActorHopTarget)
5828+
emission.setImplicitlyAsync(implicitActorHopTarget);
5829+
58255830
// Self ->
58265831
if (hasSelf) {
58275832
emission.addSelfParam(loc, std::move(selfValue),

lib/SILGen/SILGenFunction.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,12 +1440,14 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
14401440
CanType baseFormalType,
14411441
SILDeclRef accessor);
14421442

1443-
RValue emitGetAccessor(SILLocation loc, SILDeclRef getter,
1444-
SubstitutionMap substitutions,
1445-
ArgumentSource &&optionalSelfValue, bool isSuper,
1446-
bool isDirectAccessorUse,
1447-
PreparedArguments &&optionalSubscripts, SGFContext C,
1448-
bool isOnSelfParameter);
1443+
RValue emitGetAccessor(
1444+
SILLocation loc, SILDeclRef getter,
1445+
SubstitutionMap substitutions,
1446+
ArgumentSource &&optionalSelfValue, bool isSuper,
1447+
bool isDirectAccessorUse,
1448+
PreparedArguments &&optionalSubscripts, SGFContext C,
1449+
bool isOnSelfParameter,
1450+
Optional<ImplicitActorHopTarget> implicitActorHopTarget = None);
14491451

14501452
void emitSetAccessor(SILLocation loc, SILDeclRef setter,
14511453
SubstitutionMap substitutions,

lib/SILGen/SILGenLValue.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,26 +1641,26 @@ namespace {
16411641
assert(getAccessorDecl()->isGetter());
16421642

16431643
SILDeclRef getter = Accessor;
1644-
ExecutorBreadcrumb prevExecutor;
16451644
RValue rvalue;
1646-
{
1647-
FormalEvaluationScope scope(SGF);
1648-
1649-
// If the 'get' is in the context of the target's actor, do a hop first.
1650-
prevExecutor = SGF.emitHopToTargetActor(loc, ActorIso, base);
1651-
1652-
auto args =
1653-
std::move(*this).prepareAccessorArgs(SGF, loc, base, getter);
1645+
FormalEvaluationScope scope(SGF);
16541646

1655-
rvalue = SGF.emitGetAccessor(
1656-
loc, getter, Substitutions, std::move(args.base), IsSuper,
1657-
IsDirectAccessorUse, std::move(args.Indices), c,
1658-
IsOnSelfParameter);
1647+
// FIXME: This somewhat silly, because the original expression should
1648+
// already have one of these.
1649+
Optional<ImplicitActorHopTarget> implicitActorHopTarget;
1650+
if (ActorIso) {
1651+
implicitActorHopTarget = ActorIso->isGlobalActor()
1652+
? ImplicitActorHopTarget::forGlobalActor(
1653+
ActorIso->getGlobalActor())
1654+
: ImplicitActorHopTarget::forInstanceSelf();
1655+
}
16591656

1660-
} // End the evaluation scope before any hop back to the current executor.
1657+
auto args =
1658+
std::move(*this).prepareAccessorArgs(SGF, loc, base, getter);
16611659

1662-
// If we hopped to the target's executor, then we need to hop back.
1663-
prevExecutor.emit(SGF, loc);
1660+
rvalue = SGF.emitGetAccessor(
1661+
loc, getter, Substitutions, std::move(args.base), IsSuper,
1662+
IsDirectAccessorUse, std::move(args.Indices), c,
1663+
IsOnSelfParameter, implicitActorHopTarget);
16641664

16651665
return rvalue;
16661666
}

0 commit comments

Comments
 (0)