Skip to content

Commit 2d0911c

Browse files
committed
implementation of async actor properties in SILGen
The strategy for implementing them is integrated with the PathComponent infrastructure in SILGen in order to correctly support mixtures of chained accesses and forced optionals, etc. The actor isolation information is only piped into LValues from the expressions that might be marked implicitly-async.
1 parent bf171ed commit 2d0911c

File tree

6 files changed

+222
-104
lines changed

6 files changed

+222
-104
lines changed

lib/SILGen/LValue.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,16 @@ class PhysicalPathComponent : public PathComponent {
209209
virtual void _anchor() override;
210210

211211
protected:
212-
PhysicalPathComponent(LValueTypeData typeData, KindTy Kind)
213-
: PathComponent(typeData, Kind) {
212+
Optional<ActorIsolation> ActorIso;
213+
PhysicalPathComponent(LValueTypeData typeData, KindTy Kind,
214+
Optional<ActorIsolation> actorIso = None)
215+
: PathComponent(typeData, Kind), ActorIso(actorIso) {
214216
assert(isPhysical() && "PhysicalPathComponent Kind isn't physical");
215217
}
218+
219+
public:
220+
// Obtains the actor-isolation required for any loads of this component.
221+
Optional<ActorIsolation> getActorIsolation() const { return ActorIso; }
216222
};
217223

218224
inline PhysicalPathComponent &PathComponent::asPhysical() {
@@ -421,12 +427,19 @@ class LValue {
421427
Path.emplace_back(new T(std::forward<As>(args)...));
422428
}
423429

430+
// NOTE: Optional<ActorIsolation> inside of LValues
431+
// Some path components carry an ActorIsolation value, which is an indicator
432+
// that the access to that component must be performed by switching to the
433+
// given actor's isolation domain. If the indicator is not present, that
434+
// only means that a switch does not need to be emitted during the access.
435+
424436
void addNonMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
425437
VarDecl *var, SubstitutionMap subs,
426438
LValueOptions options,
427439
SGFAccessKind accessKind,
428440
AccessStrategy strategy,
429-
CanType formalRValueType);
441+
CanType formalRValueType,
442+
Optional<ActorIsolation> actorIso = None);
430443

431444
/// Add a member component to the access path of this lvalue.
432445
void addMemberComponent(SILGenFunction &SGF, SILLocation loc,
@@ -448,7 +461,8 @@ class LValue {
448461
SGFAccessKind accessKind,
449462
AccessStrategy accessStrategy,
450463
CanType formalRValueType,
451-
bool isOnSelf = false);
464+
bool isOnSelf = false,
465+
Optional<ActorIsolation> actorIso = None);
452466

453467
void addMemberSubscriptComponent(SILGenFunction &SGF, SILLocation loc,
454468
SubscriptDecl *subscript,
@@ -460,7 +474,8 @@ class LValue {
460474
CanType formalRValueType,
461475
PreparedArguments &&indices,
462476
Expr *indexExprForDiagnostics,
463-
bool isOnSelfParameter = false);
477+
bool isOnSelfParameter = false,
478+
Optional<ActorIsolation> actorIso = None);
464479

465480
/// Add a subst-to-orig reabstraction component. That is, given
466481
/// that this l-value trafficks in values following the substituted

lib/SILGen/SILGenApply.cpp

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4285,30 +4285,6 @@ bool SILGenModule::isNonMutatingSelfIndirect(SILDeclRef methodRef) {
42854285
return self.isFormalIndirect();
42864286
}
42874287

4288-
Optional<SILValue> SILGenFunction::emitLoadActorExecutorForCallee(
4289-
ValueDecl *calleeVD,
4290-
ArrayRef<ManagedValue> args) {
4291-
if (auto *funcDecl = dyn_cast_or_null<AbstractFunctionDecl>(calleeVD)) {
4292-
auto actorIso = getActorIsolation(funcDecl);
4293-
switch (actorIso.getKind()) {
4294-
case ActorIsolation::Unspecified:
4295-
case ActorIsolation::Independent:
4296-
case ActorIsolation::IndependentUnsafe:
4297-
break;
4298-
4299-
case ActorIsolation::ActorInstance: {
4300-
assert(args.size() > 0 && "no self argument for actor-instance call?");
4301-
auto calleeSelf = args.back();
4302-
return calleeSelf.borrow(*this, F.getLocation()).getValue();
4303-
}
4304-
4305-
case ActorIsolation::GlobalActor:
4306-
case ActorIsolation::GlobalActorUnsafe:
4307-
return emitLoadGlobalActorExecutor(actorIso.getGlobalActor());
4308-
}
4309-
}
4310-
return None;
4311-
}
43124288

43134289
//===----------------------------------------------------------------------===//
43144290
// Top Level Entrypoints
@@ -4418,10 +4394,16 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
44184394
assert(F.isAsync() && "cannot hop_to_executor in a non-async func!");
44194395

44204396
auto calleeVD = implicitlyAsyncApply.getValue();
4421-
auto maybeExecutor = emitLoadActorExecutorForCallee(calleeVD, args);
4397+
if (auto *funcDecl = dyn_cast_or_null<AbstractFunctionDecl>(calleeVD)) {
4398+
Optional<ManagedValue> actorSelf;
44224399

4423-
assert(maybeExecutor.hasValue());
4424-
B.createHopToExecutor(loc, maybeExecutor.getValue());
4400+
if (args.size() > 0)
4401+
actorSelf = args.back();
4402+
4403+
auto didHop = emitHopToTargetActor(loc, getActorIsolation(funcDecl),
4404+
actorSelf);
4405+
assert(didHop);
4406+
}
44254407
}
44264408

44274409
SILValue rawDirectResult;

lib/SILGen/SILGenExpr.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,6 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
927927
}
928928

929929
RValue RValueEmitter::visitDeclRefExpr(DeclRefExpr *E, SGFContext C) {
930-
assert(!E->isImplicitlyAsync() && "TODO: Implement SILGen lowering");
931930
return SGF.emitRValueForDecl(E, E->getDeclRef(), E->getType(),
932931
E->getAccessSemantics(), C);
933932
}
@@ -2183,7 +2182,6 @@ RValue RValueEmitter::visitMemberRefExpr(MemberRefExpr *e,
21832182
assert(!e->getType()->is<LValueType>() &&
21842183
"RValueEmitter shouldn't be called on lvalues");
21852184
assert(isa<VarDecl>(e->getMember().getDecl()));
2186-
assert(!e->isImplicitlyAsync() && "TODO: Implement SILGen lowering");
21872185

21882186
// Everything else should use the l-value logic.
21892187

@@ -2211,7 +2209,6 @@ visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *E, SGFContext C) {
22112209
}
22122210

22132211
RValue RValueEmitter::visitSubscriptExpr(SubscriptExpr *E, SGFContext C) {
2214-
assert(!E->isImplicitlyAsync() && "TODO: Implement SILGen lowering");
22152212
// Any writebacks for this access are tightly scoped.
22162213
FormalEvaluationScope scope(SGF);
22172214

lib/SILGen/SILGenFunction.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -857,12 +857,13 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
857857
// Concurrency
858858
//===--------------------------------------------------------------------===//
859859

860-
/// Generates code to obtain the callee function's executor, if the function
861-
/// is actor-isolated.
860+
/// Generates code to obtain the executor for the given actor isolation,
861+
/// as-needed, and emits a \c hop_to_executor to that executor.
862862
///
863-
/// \returns a SILValue representing the executor, if an executor exists.
864-
Optional<SILValue> emitLoadActorExecutorForCallee(ValueDecl *calleeVD,
865-
ArrayRef<ManagedValue> args);
863+
/// \returns a non-null pointer if a \c hop_to_executor was emitted.
864+
HopToExecutorInst* emitHopToTargetActor(SILLocation loc,
865+
Optional<ActorIsolation> actorIso,
866+
Optional<ManagedValue> actorSelf);
866867

867868
/// Generates code to obtain the executor given the actor's decl.
868869
/// \returns a SILValue representing the executor.

0 commit comments

Comments
 (0)