Skip to content

[WIP] distributed computed properties #42321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class ASTMangler : public Mangler {
Type GlobalActorBound,
ModuleDecl *Module);

std::string mangleDistributedThunk(const FuncDecl *thunk);
std::string mangleDistributedThunk(const AbstractFunctionDecl *thunk);

/// Mangle a completion handler block implementation function, used for importing ObjC
/// APIs as async.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/Attr.def
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ SIMPLE_DECL_ATTR(_inheritActorContext, InheritActorContext,
// 117 was 'spawn' and is now unused

CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor,
DeclModifier | OnClass | OnFunc | OnVar |
DeclModifier | OnClass | OnFunc | OnAccessor | OnVar |
ABIBreakingToAdd | ABIBreakingToRemove |
APIBreakingToAdd | APIBreakingToRemove,
118)
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4811,6 +4811,9 @@ ERROR(distributed_property_cannot_be_static,none,
ERROR(distributed_property_can_only_be_computed,none,
"%0 %1 cannot be 'distributed', only computed properties can",
(DescriptiveDeclKind, DeclName))
ERROR(distributed_property_accessor_only_get_can_be_distributed,none,
"only 'get' accessors may be 'distributed'",
())
NOTE(distributed_actor_isolated_property,none,
"access to %0 %1 is only permitted within distributed actor %2",
(DescriptiveDeclKind, DeclName, DeclName))
Expand Down
17 changes: 15 additions & 2 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,11 @@ class alignas(8) Expr : public ASTAllocated<Expr> {

SWIFT_INLINE_BITFIELD_EMPTY(LiteralExpr, Expr);
SWIFT_INLINE_BITFIELD_EMPTY(IdentityExpr, Expr);
SWIFT_INLINE_BITFIELD(LookupExpr, Expr, 1+1+1,
SWIFT_INLINE_BITFIELD(LookupExpr, Expr, 1+1+1+1,
IsSuper : 1,
IsImplicitlyAsync : 1,
IsImplicitlyThrows : 1
IsImplicitlyThrows : 1,
ShouldApplyDistributedThunk: 1
);
SWIFT_INLINE_BITFIELD_EMPTY(DynamicLookupExpr, LookupExpr);

Expand Down Expand Up @@ -1655,6 +1656,18 @@ class LookupExpr : public Expr {
Bits.LookupExpr.IsImplicitlyThrows = isImplicitlyThrows;
}

/// Informs IRGen to that this expression should be applied as its distributed
/// thunk, rather than invoking the function directly.
///
/// Only intended to be set on distributed get-only computed properties.
bool shouldApplyLookupDistributedThunk() const {
return Bits.LookupExpr.ShouldApplyDistributedThunk;
}

void setShouldApplyLookupDistributedThunk(bool flag) {
Bits.LookupExpr.ShouldApplyDistributedThunk = flag;
}

static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_LookupExpr &&
E->getKind() <= ExprKind::Last_LookupExpr;
Expand Down
8 changes: 8 additions & 0 deletions include/swift/AST/StorageImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ class AccessStrategy {
/// separately performing a Read into a temporary variable followed by
/// a Write access back into the storage.
MaterializeToTemporary,

// /// The access is to a computed distributed property, and thus the
// /// get-accessor is a distributed thunk which may perform a remote call.
// DirectToDistributedThunkAccessor,
};

private:
Expand Down Expand Up @@ -149,6 +153,10 @@ class AccessStrategy {
return { dispatched ? DispatchToAccessor : DirectToAccessor, accessor };
}

// static AccessStrategy getDistributedGetAccessor(AccessorKind accessor) {
// assert(accessor == AccessorKind::Get);
// return { DirectToDistributedThunkAccessor, accessor };
// }
static AccessStrategy getMaterializeToTemporary(AccessStrategy read,
AccessStrategy write) {
return { read, write };
Expand Down
5 changes: 5 additions & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,8 @@ namespace {

void visitVarDecl(VarDecl *VD) {
printCommon(VD, "var_decl");
if (VD->isDistributed())
PrintWithColorRAII(OS, DeclModifierColor) << " distributed";
if (VD->isLet())
PrintWithColorRAII(OS, DeclModifierColor) << " let";
if (VD->getAttrs().hasAttribute<LazyAttr>())
Expand Down Expand Up @@ -2015,6 +2017,9 @@ class PrintExpr : public ExprVisitor<PrintExpr> {

void visitMemberRefExpr(MemberRefExpr *E) {
printCommon(E, "member_ref_expr");
if (E->shouldApplyLookupDistributedThunk()) {
OS << " distributed";
}
PrintWithColorRAII(OS, DeclColor) << " decl=";
printDeclRef(E->getMember());
if (E->getAccessSemantics() != AccessSemantics::Ordinary)
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3458,7 +3458,7 @@ ASTMangler::mangleOpaqueTypeDescriptorRecord(const OpaqueTypeDecl *decl) {
return finalize();
}

std::string ASTMangler::mangleDistributedThunk(const FuncDecl *thunk) {
std::string ASTMangler::mangleDistributedThunk(const AbstractFunctionDecl *thunk) {
// Marker protocols cannot be checked at runtime, so there is no point
// in recording them for distributed thunks.
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(AllowMarkerProtocols,
Expand Down
19 changes: 19 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2137,6 +2137,17 @@ getDirectReadAccessStrategy(const AbstractStorageDecl *storage) {
llvm_unreachable("bad impl kind");
}

//static AccessStrategy
//getDirectToDistributedThunkAccessorStrategy(const AbstractStorageDecl *storage) {
// switch (storage->getReadImpl()) {
// case ReadImplKind::Get:
// return AccessStrategy::getDistributedGetAccessor(AccessorKind::Get);
// default:
// llvm_unreachable("bad impl kind for distributed property accessor");
// }
// llvm_unreachable("bad impl kind for distributed property accessor");
//}

static AccessStrategy
getDirectWriteAccessStrategy(const AbstractStorageDecl *storage) {
switch (storage->getWriteImpl()) {
Expand Down Expand Up @@ -2270,6 +2281,14 @@ AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
if (shouldUseNativeDynamicDispatch())
return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ false);

// if (auto var = dyn_cast<VarDecl>(this)) {
// if (var->isDistributed()) {
// fprintf(stderr, "[%s:%d] (%s) DIST STRATEGY!!\n", __FILE__, __LINE__, __FUNCTION__);
// var->dump();
// return getDirectToDistributedThunkAccessorStrategy(this);
// }
// }

// If the storage is resilient from the given module and resilience
// expansion, we cannot use direct access.
//
Expand Down
4 changes: 4 additions & 0 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,9 @@ void SILGenModule::visitVarDecl(VarDecl *vd) {
if (vd->hasStorage())
addGlobalVariable(vd);

fprintf(stderr, "[%s:%d] (%s) VISIT VAR DECL\n", __FILE__, __LINE__, __FUNCTION__);
vd->dump();

vd->visitEmittedAccessors([&](AccessorDecl *accessor) {
emitFunction(accessor);
});
Expand Down Expand Up @@ -1828,6 +1831,7 @@ SILGenModule::canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl,
case AccessStrategy::DirectToAccessor:
case AccessStrategy::DispatchToAccessor:
case AccessStrategy::MaterializeToTemporary:
// case AccessStrategy::DirectToDistributedThunkAccessor:
return false;
}
llvm_unreachable("unhandled strategy");
Expand Down
36 changes: 25 additions & 11 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {

// If this is a direct reference to a vardecl, just emit its value directly.
// Recursive references to callable declarations are allowed.
if (isa<VarDecl>(e->getDecl())) {
if (auto var = dyn_cast<VarDecl>(e->getDecl())) {
visitExpr(e);
return;
}
Expand Down Expand Up @@ -1123,6 +1123,8 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {

/// Some special handling may be necessary for thunks:
if (callSite && callSite->shouldApplyDistributedThunk()) {
fprintf(stderr, "[%s:%d] (%s) SHOULD APPLY DIST THUNK\n", __FILE__, __LINE__, __FUNCTION__);

if (auto distributedThunk = cast<AbstractFunctionDecl>(e->getDecl())->getDistributedThunk()) {
constant = SILDeclRef(distributedThunk).asDistributed();
}
Expand Down Expand Up @@ -5383,6 +5385,7 @@ static Callee getBaseAccessorFunctionRef(SILGenFunction &SGF,
ArgumentSource &selfValue,
bool isSuper,
bool isDirectUse,
bool isDistributed,
SubstitutionMap subs,
bool isOnSelfParameter) {
auto *decl = cast<AbstractFunctionDecl>(constant.getDecl());
Expand Down Expand Up @@ -5462,12 +5465,13 @@ emitSpecializedAccessorFunctionRef(SILGenFunction &SGF,
ArgumentSource &selfValue,
bool isSuper,
bool isDirectUse,
bool isDistributed,
bool isOnSelfParameter)
{
// Get the accessor function. The type will be a polymorphic function if
// the Self type is generic.
Callee callee = getBaseAccessorFunctionRef(SGF, loc, constant, selfValue,
isSuper, isDirectUse,
isSuper, isDirectUse, isDistributed,
substitutions, isOnSelfParameter);

// Collect captures if the accessor has them.
Expand Down Expand Up @@ -5779,15 +5783,23 @@ SILDeclRef SILGenModule::getAccessorDeclRef(AccessorDecl *accessor) {
RValue SILGenFunction::emitGetAccessor(SILLocation loc, SILDeclRef get,
SubstitutionMap substitutions,
ArgumentSource &&selfValue, bool isSuper,
bool isDirectUse,
bool isDirectUse, bool isDistributed,
PreparedArguments &&subscriptIndices,
SGFContext c, bool isOnSelfParameter) {
SGFContext c,
bool isOnSelfParameter) {
// Scope any further writeback just within this operation.
FormalEvaluationScope writebackScope(*this);

auto constant = get;

// if (isDistributed) {
// get.dump();
// assert(false && "should use dist thunk");
// }

Callee getter = emitSpecializedAccessorFunctionRef(
*this, loc, get, substitutions, selfValue, isSuper, isDirectUse,
isOnSelfParameter);
*this, loc, constant, substitutions, selfValue, isSuper, isDirectUse,
isDistributed, isOnSelfParameter);
bool hasSelf = (bool)selfValue;
CanAnyFunctionType accessType = getter.getSubstFormalType();

Expand Down Expand Up @@ -5820,7 +5832,7 @@ void SILGenFunction::emitSetAccessor(SILLocation loc, SILDeclRef set,

Callee setter = emitSpecializedAccessorFunctionRef(
*this, loc, set, substitutions, selfValue, isSuper, isDirectUse,
isOnSelfParameter);
/*isDistributed=*/false, isOnSelfParameter);
bool hasSelf = (bool)selfValue;
CanAnyFunctionType accessType = setter.getSubstFormalType();

Expand Down Expand Up @@ -5855,14 +5867,14 @@ void SILGenFunction::emitSetAccessor(SILLocation loc, SILDeclRef set,
ManagedValue SILGenFunction::emitAddressorAccessor(
SILLocation loc, SILDeclRef addressor, SubstitutionMap substitutions,
ArgumentSource &&selfValue, bool isSuper, bool isDirectUse,
PreparedArguments &&subscriptIndices, SILType addressType,
bool isOnSelfParameter) {
bool isDistributed, PreparedArguments &&subscriptIndices,
SILType addressType, bool isOnSelfParameter) {
// Scope any further writeback just within this operation.
FormalEvaluationScope writebackScope(*this);

Callee callee = emitSpecializedAccessorFunctionRef(
*this, loc, addressor, substitutions, selfValue, isSuper, isDirectUse,
isOnSelfParameter);
isDistributed, isOnSelfParameter);
bool hasSelf = (bool)selfValue;
CanAnyFunctionType accessType = callee.getSubstFormalType();

Expand Down Expand Up @@ -5917,7 +5929,9 @@ SILGenFunction::emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor,
Callee callee =
emitSpecializedAccessorFunctionRef(*this, loc, accessor,
substitutions, selfValue,
isSuper, isDirectUse, isOnSelfParameter);
isSuper, isDirectUse,
/*isDistributed=*/false,
isOnSelfParameter);

// We're already in a full formal-evaluation scope.
// Make a dead writeback scope; applyCoroutine won't try to pop this.
Expand Down
1 change: 1 addition & 0 deletions lib/SILGen/SILGenDistributed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ void SILGenFunction::emitDistActorIdentityInit(ConstructorDecl *ctor,
initializeProperty(*this, loc, borrowedSelfArg, var, temp);
}

// TODO(distributed): rename to DistributedActorID
InitializeDistActorIdentity::InitializeDistActorIdentity(ConstructorDecl *ctor,
ManagedValue actorSelf)
: ctor(ctor),
Expand Down
17 changes: 17 additions & 0 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3444,6 +3444,23 @@ getIdForKeyPathComponentComputedProperty(SILGenModule &SGM,
// stable identifier.
return SGM.getFunction(getterRef, NotForDefinition);
}
// case AccessStrategy::DirectToDistributedThunkAccessor: {
// assert(false && "dont need this");
// // Locate the distributed thunk for the getter of this property
// fprintf(stderr, "[%s:%d] (%s) CHECKING.... DirectToDistributedThunkAccessor\n", __FILE__, __LINE__, __FUNCTION__);
// auto representativeDecl = getRepresentativeAccessorForKeyPath(storage);
// assert(representativeDecl->isDistributed());
// fprintf(stderr, "[%s:%d] (%s) OK, representative is DIST\n", __FILE__, __LINE__, __FUNCTION__);
//
// auto getterThunkRef = SILDeclRef(representativeDecl->getDistributedThunk(),
// SILDeclRef::Kind::Func,
// /*isForeign=*/false,
// /*isDistributed=*/true);
// fprintf(stderr, "[%s:%d] (%s) THUNK\n", __FILE__, __LINE__, __FUNCTION__);
// getterThunkRef.dump();
//
// return SGM.getFunction(getterThunkRef, NotForDefinition);
// }
case AccessStrategy::DispatchToAccessor: {
// Identify the property by its vtable or wtable slot.
return SGM.getAccessorDeclRef(getRepresentativeAccessorForKeyPath(storage));
Expand Down
4 changes: 3 additions & 1 deletion lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
SubstitutionMap substitutions,
ArgumentSource &&optionalSelfValue, bool isSuper,
bool isDirectAccessorUse,
bool isDistributed,
PreparedArguments &&optionalSubscripts, SGFContext C,
bool isOnSelfParameter);

Expand Down Expand Up @@ -1476,7 +1477,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
ManagedValue emitAddressorAccessor(
SILLocation loc, SILDeclRef addressor, SubstitutionMap substitutions,
ArgumentSource &&optionalSelfValue, bool isSuper,
bool isDirectAccessorUse, PreparedArguments &&optionalSubscripts,
bool isDirectAccessorUse, bool isDistributed,
PreparedArguments &&optionalSubscripts,
SILType addressType, bool isOnSelfParameter);

CleanupHandle emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor,
Expand Down
Loading