@@ -81,44 +81,48 @@ struct ArgumentDecoderInfo {
81
81
// / The type of `decodeNextArgument` method.
82
82
CanSILFunctionType MethodType;
83
83
84
- // / Protocol requirements associated with the generic
85
- // / parameter `Argument` of this decode method.
86
- GenericSignature::RequiredProtocols ProtocolRequirements;
87
-
88
- // Witness metadata for conformance to DistributedTargetInvocationDecoder
89
- // protocol.
84
+ // / Witness metadata for conformance to DistributedTargetInvocationDecoder
85
+ // / protocol.
90
86
WitnessMetadata Witness;
91
87
88
+ // / Indicates whether `decodeNextArgument` is referenced through
89
+ // / a protocol witness thunk.
90
+ bool UsesWitnessDispatch;
91
+
92
92
ArgumentDecoderInfo (llvm::Value *decoder, llvm::Value *decoderType,
93
93
llvm::Value *decoderWitnessTable,
94
94
FunctionPointer decodeNextArgumentPtr,
95
- CanSILFunctionType decodeNextArgumentTy)
95
+ CanSILFunctionType decodeNextArgumentTy,
96
+ bool usesWitnessDispatch)
96
97
: Decoder(decoder), MethodPtr(decodeNextArgumentPtr),
97
98
MethodType (decodeNextArgumentTy),
98
- ProtocolRequirements(findProtocolRequirements(decodeNextArgumentTy) ) {
99
+ UsesWitnessDispatch(usesWitnessDispatch ) {
99
100
Witness.SelfMetadata = decoderType;
100
101
Witness.SelfWitnessTable = decoderWitnessTable;
101
102
}
102
103
103
104
CanSILFunctionType getMethodType () const { return MethodType; }
104
105
105
- ArrayRef<ProtocolDecl *> getProtocolRequirements () const {
106
- return ProtocolRequirements ;
106
+ WitnessMetadata * getWitnessMetadata () const {
107
+ return const_cast <WitnessMetadata *>(&Witness) ;
107
108
}
108
109
109
- // / Form a callee to a decode method - `decodeNextArgument`.
110
- Callee getCallee () const ;
110
+ // / Protocol requirements associated with the generic
111
+ // / parameter `Argument` of this decode method.
112
+ GenericSignature::RequiredProtocols getProtocolRequirements () const {
113
+ if (UsesWitnessDispatch)
114
+ return {};
111
115
112
- private:
113
- static GenericSignature::RequiredProtocols
114
- findProtocolRequirements (CanSILFunctionType decodeMethodTy) {
115
- auto signature = decodeMethodTy->getInvocationGenericSignature ();
116
+ auto signature = MethodType->getInvocationGenericSignature ();
116
117
auto genericParams = signature.getGenericParams ();
117
118
118
119
// func decodeNextArgument<Arg : #SerializationRequirement#>() throws -> Arg
119
120
assert (genericParams.size () == 1 );
120
121
return signature->getRequiredProtocols (genericParams.front ());
121
122
}
123
+
124
+ // / Form a callee to a decode method - `decodeNextArgument`.
125
+ Callee getCallee () const ;
122
126
};
123
127
124
128
class DistributedAccessor {
@@ -415,7 +419,8 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
415
419
emission->begin ();
416
420
{
417
421
emission->setArgs (decodeArgs, /* isOutlined=*/ false ,
418
- /* witnessMetadata=*/ nullptr );
422
+ decoder.UsesWitnessDispatch ? decoder.getWitnessMetadata ()
423
+ : nullptr );
419
424
420
425
Explosion result;
421
426
emission->emitToExplosion (result, /* isOutlined=*/ false );
@@ -519,6 +524,9 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
519
524
void DistributedAccessor::lookupWitnessTables (
520
525
llvm::Value *value, ArrayRef<ProtocolDecl *> protocols,
521
526
Explosion &witnessTables) {
527
+ if (protocols.empty ())
528
+ return ;
529
+
522
530
auto conformsToProtocol = IGM.getConformsToProtocolFunctionPointer ();
523
531
524
532
for (auto *protocol : protocols) {
@@ -785,11 +793,32 @@ DistributedAccessor::getCalleeForDistributedTarget(llvm::Value *self) const {
785
793
786
794
ArgumentDecoderInfo DistributedAccessor::findArgumentDecoder (
787
795
llvm::Value *decoder, llvm::Value *decoderTy, llvm::Value *witnessTable) {
796
+ auto &C = IGM.Context ;
788
797
auto *actor = getDistributedActorOf (Target);
789
798
auto expansionContext = IGM.getMaximalTypeExpansionContext ();
790
799
791
- auto *decodeFn = IGM.Context .getDistributedActorArgumentDecodingMethod (actor);
792
- assert (decodeFn && " no suitable decoder?" );
800
+ auto *decodeFn = C.getDistributedActorArgumentDecodingMethod (actor);
801
+
802
+ // If distributed actor is generic over actor system, we have to
803
+ // use witness to reference `decodeNextArgument`.
804
+ if (!decodeFn) {
805
+ auto decoderProtocol = C.getDistributedTargetInvocationDecoderDecl ();
806
+ auto decodeNextArgRequirement =
807
+ decoderProtocol->getSingleRequirement (C.Id_decodeNextArgument );
808
+ assert (decodeNextArgRequirement);
809
+ SILDeclRef decodeNextArgumentRef (decodeNextArgRequirement);
810
+
811
+ llvm::Constant *fnPtr =
812
+ IGM.getAddrOfDispatchThunk (decodeNextArgumentRef, NotForDefinition);
813
+ auto fnType = IGM.getSILTypes ().getConstantFunctionType (
814
+ IGM.getMaximalTypeExpansionContext (), decodeNextArgumentRef);
815
+
816
+ auto sig = IGM.getSignature (fnType);
817
+ auto fn = FunctionPointer::forDirect (fnType, fnPtr,
818
+ /* secondaryValue=*/ nullptr , sig, true );
819
+ return {decoder, decoderTy, witnessTable,
820
+ fn, fnType, /* usesWitnessDispatch=*/ true };
821
+ }
793
822
794
823
auto methodTy = IGM.getSILTypes ().getConstantFunctionType (
795
824
expansionContext, SILDeclRef (decodeFn));
@@ -848,7 +877,8 @@ ArgumentDecoderInfo DistributedAccessor::findArgumentDecoder(
848
877
/* secondaryValue=*/ nullptr , signature);
849
878
}
850
879
851
- return {decoder, decoderTy, witnessTable, methodPtr, methodTy};
880
+ return {decoder, decoderTy, witnessTable,
881
+ methodPtr, methodTy, /* usesWitnessDispatch=*/ false };
852
882
}
853
883
854
884
SILType DistributedAccessor::getResultType () const {
0 commit comments