Skip to content

Commit dfdbe45

Browse files
authored
[Distributed] Support complex generic distributed actors in thunk gen (#70842)
1 parent 5a67add commit dfdbe45

8 files changed

+111
-37
lines changed

lib/IRGen/GenDistributed.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ static CanSILFunctionType getAccessorType(IRGenModule &IGM,
221221
// A generic parameter that represents instance of invocation decoder.
222222
auto *decoderType =
223223
GenericTypeParamType::get(/*isParameterPack=*/false,
224-
/*depth=*/1, /*index=*/0, Context);
224+
/*depth=*/0, /*index=*/0, Context);
225225

226226
// decoder
227227
parameters.push_back(GenericFunctionType::Param(
@@ -249,13 +249,15 @@ static CanSILFunctionType getAccessorType(IRGenModule &IGM,
249249
parameters.push_back(GenericFunctionType::Param(Context.getUIntType()));
250250

251251
// actor
252-
{
253-
auto targetTy = Target->getLoweredFunctionType();
254-
auto actorLoc = targetTy->getParameters().back();
255252

253+
auto actorTypeParam =
254+
GenericTypeParamType::get(/*isParameterPack=*/false,
255+
/*depth=*/0, /*index=*/1, Context);
256256
parameters.push_back(
257-
GenericFunctionType::Param(actorLoc.getInterfaceType()));
258-
}
257+
GenericFunctionType::Param(actorTypeParam));
258+
auto distributedActorTy =
259+
Context.getDistributedActorDecl()
260+
->getDeclaredInterfaceType();
259261

260262
auto decoderProtocolTy =
261263
Context
@@ -268,11 +270,8 @@ static CanSILFunctionType getAccessorType(IRGenModule &IGM,
268270
SmallVector<GenericTypeParamType *, 4> genericParams;
269271
SmallVector<Requirement, 4> genericRequirements;
270272

271-
auto *actor = getDistributedActorOf(Target);
272-
assert(actor);
273-
274-
for (auto *genericParam : actor->getInnermostGenericParamTypes())
275-
genericParams.push_back(genericParam);
273+
assert(getDistributedActorOf(Target) &&
274+
"target must be declared inside distributed actor");
276275

277276
// Add a generic parameter `D` which stands for decoder type in the
278277
// accessor signature - `inout D`.
@@ -281,7 +280,14 @@ static CanSILFunctionType getAccessorType(IRGenModule &IGM,
281280
genericRequirements.push_back(
282281
{RequirementKind::Conformance, decoderType, decoderProtocolTy});
283282

284-
signature = GenericSignature::get(genericParams, genericRequirements);
283+
genericRequirements.push_back(
284+
{RequirementKind::Conformance, actorTypeParam, distributedActorTy});
285+
286+
genericParams.push_back(actorTypeParam);
287+
288+
signature = buildGenericSignature(Context, GenericSignature(),
289+
std::move(genericParams),
290+
std::move(genericRequirements));
285291
}
286292

287293
auto accessorTy = GenericFunctionType::get(
@@ -650,14 +656,13 @@ void DistributedAccessor::emit() {
650656
// Metadata that represents passed in the invocation decoder.
651657
auto *decoderType = params.claimNext();
652658

653-
// If the distributed thunk is declared in a protocol that conforms
654-
// to `DistributedActor` protocol, there is an extract parameter that
655-
// represents a type of protocol witness.
656-
if (isa<ProtocolDecl>(actor))
657-
(void)params.claimNext();
659+
// Metadata that represents the actor the invocation is on.
660+
auto *actorType = params.claimNext();
661+
(void)actorType;
658662

659663
// Witness table for decoder conformance to DistributedTargetInvocationDecoder
660664
auto *decoderProtocolWitness = params.claimNext();
665+
auto *distributedActorWitness = params.claimNext();
661666

662667
// Preliminary: Setup async context for this accessor.
663668
{

stdlib/public/Distributed/DistributedActor.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ using TargetExecutorSignature =
6161
/*witnessTables=*/void **,
6262
/*numWitnessTables=*/size_t,
6363
/*decoderType=*/Metadata *,
64-
/*decoderWitnessTable=*/void **),
64+
/*actorType=*/Metadata *,
65+
/*decoderWitnessTable=*/void **,
66+
/*distributedActorWitnessTable=*/void **
67+
),
6568
/*throws=*/true>;
6669

6770
SWIFT_CC(swiftasync)
@@ -88,7 +91,9 @@ using DistributedAccessorSignature =
8891
/*numWitnessTables=*/size_t,
8992
/*actor=*/HeapObject *,
9093
/*decoderType=*/Metadata *,
91-
/*decoderWitnessTable=*/void **),
94+
/*actorType=*/Metadata *,
95+
/*decoderWitnessTable=*/void **,
96+
/*actorWitnessTable=*/void **),
9297
/*throws=*/true>;
9398

9499
SWIFT_CC(swiftasync)
@@ -124,7 +129,9 @@ void swift_distributed_execute_target(
124129
void **witnessTables,
125130
size_t numWitnessTables,
126131
Metadata *decoderType,
127-
void **decoderWitnessTable) {
132+
Metadata *actorType,
133+
void **decoderWitnessTable,
134+
void **actorWitnessTable) {
128135
auto *accessor = findDistributedAccessor(targetNameStart, targetNameLength);
129136
if (!accessor) {
130137
SwiftError *error =
@@ -159,5 +166,7 @@ void swift_distributed_execute_target(
159166
numWitnessTables,
160167
actor,
161168
decoderType,
162-
decoderWitnessTable);
169+
actorType,
170+
decoderWitnessTable,
171+
actorWitnessTable);
163172
}

stdlib/public/Distributed/DistributedActorSystem.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,8 @@ public struct RemoteCallTarget: CustomStringConvertible, Hashable {
670670

671671
@available(SwiftStdlib 5.7, *)
672672
@_silgen_name("swift_distributed_execute_target")
673-
func _executeDistributedTarget<D: DistributedTargetInvocationDecoder>(
674-
on actor: AnyObject, // DistributedActor
673+
func _executeDistributedTarget<D: DistributedTargetInvocationDecoder, DA: DistributedActor>(
674+
on actor: DA, // DistributedActor
675675
_ targetName: UnsafePointer<UInt8>, _ targetNameLength: UInt,
676676
argumentDecoder: inout D,
677677
argumentTypes: Builtin.RawPointer,

test/Distributed/Runtime/distributed_actor_func_calls_decoded_args_deinit.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -disable-availability-checking %S/../Inputs/FakeDistributedActorSystems.swift
33
// RUN: %target-build-swift -module-name main -O -Xfrontend -disable-availability-checking -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
44
// RUN: %target-codesign %t/a.out
5-
// RUN: %target-run %t/a.out | %FileCheck %s --color --dump-input=always
5+
// RUN: %target-run %t/a.out | %FileCheck %s --color
66

77
// REQUIRES: executable_test
88
// REQUIRES: concurrency
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -disable-availability-checking %S/../Inputs/FakeDistributedActorSystems.swift
3+
// RUN: %target-build-swift -module-name main -Xfrontend -disable-availability-checking -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
4+
// RUN: %target-codesign %t/a.out
5+
// RUN: %target-run %t/a.out | %FileCheck %s --color
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: concurrency
9+
// REQUIRES: distributed
10+
11+
// rdar://76038845
12+
// UNSUPPORTED: use_os_stdlib
13+
// UNSUPPORTED: back_deployment_runtime
14+
15+
// FIXME(distributed): Distributed has some issues on windows currently, see also: rdar://82593574
16+
// UNSUPPORTED: OS=windows-msvc
17+
18+
import Distributed
19+
import FakeDistributedActorSystems
20+
21+
protocol Key {
22+
static var isInteger: Bool { get }
23+
}
24+
25+
distributed actor TestActor<Object> where Object: Codable & Identifiable, Object.ID: Key {
26+
public init(actorSystem: ActorSystem) {
27+
self.actorSystem = actorSystem
28+
}
29+
30+
public distributed func handleObject(_ object: Object) async throws {
31+
print("self.id = \(object.id)")
32+
}
33+
}
34+
35+
struct SomeKey: Codable, Key, Hashable {
36+
static var isInteger: Bool { false }
37+
}
38+
39+
struct Something: Codable, Identifiable {
40+
typealias ID = SomeKey
41+
var id: SomeKey = .init()
42+
}
43+
44+
typealias DefaultDistributedActorSystem = FakeRoundtripActorSystem
45+
46+
// ==== Execute ----------------------------------------------------------------
47+
@main struct Main {
48+
static func main() async {
49+
let system = DefaultDistributedActorSystem()
50+
51+
let actor: TestActor<Something> = TestActor(actorSystem: system)
52+
let resolved: TestActor<Something> = try! .resolve(id: actor.id, using: system)
53+
try! await resolved.handleObject(Something())
54+
55+
// CHECK: self.id = SomeKey()
56+
57+
// CHECK: OK
58+
print("OK")
59+
}
60+
}

test/Distributed/Runtime/distributed_parameter_validation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -disable-availability-checking %S/../Inputs/FakeDistributedActorSystems.swift
33
// RUN: %target-build-swift -module-name main -Xfrontend -disable-availability-checking -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
44
// RUN: %target-codesign %t/a.out
5-
// RUN: %target-run %t/a.out | %FileCheck %s --color --dump-input=always
5+
// RUN: %target-run %t/a.out | %FileCheck %s --color
66

77
// REQUIRES: executable_test
88
// REQUIRES: concurrency

test/Distributed/distributed_actor_accessor_thunks_32bit.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public distributed actor MyOtherActor {
9494

9595
// CHECK: define hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7simple1yySiYaKFTE"
9696

97-
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7simple1yySiYaKFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture %1, i8* %2, i8* %3, {{.*}}, %T27distributed_actor_accessors7MyActorC* [[ACTOR:%.*]], %swift.type* [[DECODER_TYPE:%.*]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]])
97+
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7simple1yySiYaKFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture %1, i8* %2, i8* %3, {{.*}}, %T27distributed_actor_accessors7MyActorC* [[ACTOR:%.*]], %swift.type* [[DECODER_TYPE:%.*]], %swift.type* [[ACTOR_TYPE:%.*]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]], i8** [[ACTOR_WITNESS:%.*]])
9898

9999
/// Read the current offset and cast an element to `Int`
100100

@@ -194,7 +194,7 @@ public distributed actor MyOtherActor {
194194
// CHECK: define hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7simple3ySiSSYaKFTE"
195195

196196
/// !!! in `simple3` interesting bits are: argument value extraction (because string is exploded into N arguments) and call to distributed thunk
197-
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7simple3ySiSSYaKFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR]], %swift.type* [[DECODER_TYPE:%.*]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]])
197+
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7simple3ySiSSYaKFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR]], %swift.type* [[DECODER_TYPE:%.*]], %swift.type* [[ACTOR_TYPE:%.*]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]], i8** [[ACTOR_WITNESS:%.*]])
198198

199199

200200
// CHECK: [[TYPED_RESULT_BUFF:%.*]] = bitcast i8* [[RESULT_BUFF]] to %TSi*
@@ -257,7 +257,7 @@ public distributed actor MyOtherActor {
257257

258258
// CHECK: define hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC16single_case_enumyAA7SimpleEOAFYaKFTE"
259259

260-
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC16single_case_enumyAA7SimpleEOAFYaKFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR]], %swift.type* [[DECODER_TYPE]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]])
260+
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC16single_case_enumyAA7SimpleEOAFYaKFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR]], %swift.type* [[DECODER_TYPE]], %swift.type* [[ACTOR_TYPE]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]], i8** [[ACTOR_WITNESS:%.*]])
261261

262262
/// Let's check that the call doesn't have any arguments and returns nothing.
263263

@@ -303,7 +303,7 @@ public distributed actor MyOtherActor {
303303

304304
// CHECK: define hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7complexyAA11LargeStructVSaySiG_AA3ObjCSSSgAFtYaKFTE"
305305

306-
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7complexyAA11LargeStructVSaySiG_AA3ObjCSSSgAFtYaKFTETF"(%swift.context* swiftasync {{.*}}, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR]], %swift.type* [[DECODER_TYPE:%.*]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]])
306+
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC7complexyAA11LargeStructVSaySiG_AA3ObjCSSSgAFtYaKFTETF"(%swift.context* swiftasync {{.*}}, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR]], %swift.type* [[DECODER_TYPE:%.*]], %swift.type* [[ACTOR_TYPE]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]], i8** [[ACTOR_WITNESS:%.*]])
307307

308308
/// First, let's check that all of the different argument types here are loaded correctly.
309309

@@ -362,7 +362,7 @@ public distributed actor MyOtherActor {
362362

363363
/// ---> Accessor for `genericArgs`
364364

365-
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC11genericArgsyyx_Sayq_GtYaKSeRzSERzSeR_SER_r0_lFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUF:%.*]], i8* [[GENERIC_SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR:%.*]], %swift.type* [[DECODER_TYPE:%.*]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]])
365+
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors7MyActorC11genericArgsyyx_Sayq_GtYaKSeRzSERzSeR_SER_r0_lFTETF"(%swift.context* swiftasync %0, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUF:%.*]], i8* [[GENERIC_SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors7MyActorC* [[ACTOR:%.*]], %swift.type* [[DECODER_TYPE:%.*]], %swift.type* [[ACTOR_TYPE]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]], i8** [[ACTOR_WITNESS:%.*]])
366366

367367
/// ---> Load `T`
368368

@@ -418,7 +418,7 @@ public distributed actor MyOtherActor {
418418

419419
/// Let's check that there is argument decoding since parameter list is empty
420420

421-
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors12MyOtherActorC5emptyyyYaKFTETF"(%swift.context* swiftasync {{.*}}, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors12MyOtherActorC* {{.*}}, %swift.type* [[DECODER_TYPE:%.*]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]])
421+
// CHECK: define linkonce_odr hidden swift{{(tail)?}}cc void @"$s27distributed_actor_accessors12MyOtherActorC5emptyyyYaKFTETF"(%swift.context* swiftasync {{.*}}, %swift.opaque* nocapture [[ARG_DECODER:%.*]], i8* [[ARG_TYPES:%.*]], i8* [[RESULT_BUFF:%.*]], i8* [[SUBS:%.*]], i8* [[WITNESS_TABLES:%.*]], i32 [[NUM_WITNESS_TABLES:%.*]], %T27distributed_actor_accessors12MyOtherActorC* {{.*}}, %swift.type* [[DECODER_TYPE:%.*]], %swift.type* [[ACTOR_TYPE]], i8** [[DECODER_PROTOCOL_WITNESS:%.*]], i8** [[ACTOR_WITNESS:%.*]])
422422
// CHECK-NEXT: entry:
423423
// CHECK-NEXT: {{.*}} = alloca %swift.context*
424424
// CHECK-NEXT: %swifterror = alloca %swift.error*

0 commit comments

Comments
 (0)