Skip to content

Commit 9e75142

Browse files
committed
Task Executors: Prepare for new TaskExecutor protocol & builtins
1 parent e19954f commit 9e75142

23 files changed

+260
-2
lines changed

include/swift/ABI/Executor.h

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ class AsyncTask;
2828
class DefaultActor;
2929
class Job;
3030
class SerialExecutorWitnessTable;
31+
class TaskExecutorWitnessTable;
3132

32-
/// An unmanaged reference to an executor.
33+
/// An unmanaged reference to an serial executor.
3334
///
3435
/// This type corresponds to the type Optional<Builtin.Executor> in
3536
/// Swift. The representation of nil in Optional<Builtin.Executor>
@@ -182,6 +183,94 @@ class ExecutorRef {
182183
}
183184
};
184185

186+
class TaskExecutorRef {
187+
HeapObject *Identity; // Not necessarily Swift reference-countable
188+
uintptr_t Implementation;
189+
190+
// We future-proof the ABI here by masking the low bits off the
191+
// implementation pointer before using it as a witness table.
192+
//
193+
// We have 3 bits for future use remaining here.
194+
enum: uintptr_t {
195+
WitnessTableMask = ~uintptr_t(alignof(void*) - 1)
196+
};
197+
198+
/// The kind is stored in the free bits in the `Implementation` witness table reference.
199+
enum class TaskExecutorKind : uintptr_t {
200+
/// Ordinary executor.
201+
Ordinary = 0b00,
202+
};
203+
204+
static_assert(static_cast<uintptr_t>(TaskExecutorKind::Ordinary) == 0);
205+
206+
constexpr TaskExecutorRef(HeapObject *identity, uintptr_t implementation)
207+
: Identity(identity), Implementation(implementation) {}
208+
209+
public:
210+
211+
constexpr static TaskExecutorRef undefined() {
212+
return TaskExecutorRef(nullptr, 0);
213+
}
214+
215+
/// Given a pointer to a serial executor and its TaskExecutor
216+
/// conformance, return an executor reference for it.
217+
static TaskExecutorRef forOrdinary(HeapObject *identity,
218+
const SerialExecutorWitnessTable *witnessTable) {
219+
assert(identity);
220+
assert(witnessTable);
221+
auto wtable = reinterpret_cast<uintptr_t>(witnessTable) |
222+
static_cast<uintptr_t>(TaskExecutorKind::Ordinary);
223+
return TaskExecutorRef(identity, wtable);
224+
}
225+
226+
HeapObject *getIdentity() const {
227+
return Identity;
228+
}
229+
230+
/// Is this the generic executor reference?
231+
bool isUndefined() const {
232+
return Identity == 0;
233+
}
234+
235+
TaskExecutorKind getExecutorKind() const {
236+
return static_cast<TaskExecutorKind>(Implementation & ~WitnessTableMask);
237+
}
238+
239+
/// Is this an ordinary executor reference?
240+
/// These executor references are the default kind, and have no special treatment elsewhere in the system.
241+
bool isOrdinary() const {
242+
return getExecutorKind() == TaskExecutorKind::Ordinary;
243+
}
244+
245+
const SerialExecutorWitnessTable *getTaskExecutorWitnessTable() const {
246+
assert(!isUndefined());
247+
auto table = Implementation & WitnessTableMask;
248+
return reinterpret_cast<const SerialExecutorWitnessTable*>(table);
249+
}
250+
251+
// /// Do we have to do any work to start running as the requested
252+
// /// executor?
253+
// bool mustSwitchToRun(ExecutorRef newExecutor) const {
254+
// return Identity != newExecutor.Identity;
255+
// }
256+
257+
/// Get the raw value of the Implementation field, for tracing.
258+
uintptr_t getRawImplementation() const {
259+
return Implementation & WitnessTableMask;
260+
}
261+
262+
bool operator==(TaskExecutorRef other) const {
263+
return Identity == other.Identity;
264+
}
265+
bool operator!=(TaskExecutorRef other) const {
266+
return !(*this == other);
267+
}
268+
};
269+
270+
// Historically the 'ExecutorRef' was introduced initially, however it always has meant specifically
271+
// a SERIAL executor. This typedef fixes up this confusion and especially since now there is also a TaskExecutor.
272+
typedef ExecutorRef SerialExecutorRef;
273+
185274
using JobInvokeFunction =
186275
SWIFT_CC(swiftasync)
187276
void (Job *);

include/swift/AST/ASTSynthesis.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ enum SingletonTypeSynthesizer {
5050
_void,
5151
_word,
5252
_serialExecutor,
53+
_taskExecutor,
5354
};
5455
inline Type synthesizeType(SynthesisContext &SC,
5556
SingletonTypeSynthesizer kind) {
@@ -69,6 +70,9 @@ inline Type synthesizeType(SynthesisContext &SC,
6970
case _serialExecutor:
7071
return SC.Context.getProtocol(KnownProtocolKind::SerialExecutor)
7172
->getDeclaredInterfaceType();
73+
case _taskExecutor:
74+
return SC.Context.getProtocol(KnownProtocolKind::TaskExecutor)
75+
->getDeclaredInterfaceType();
7276
}
7377
}
7478

include/swift/AST/Builtins.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,11 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(AutoDiffAllocateSubcontextWithType, "autoDiff
10041004
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildOrdinarySerialExecutorRef,
10051005
"buildOrdinarySerialExecutorRef", "n", Special)
10061006

1007+
/// Build a Builtin.Executor value from an "ordinary" task executor
1008+
/// reference.
1009+
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildOrdinaryTaskExecutorRef,
1010+
"buildOrdinaryTaskExecutorRef", "n", Special)
1011+
10071012
/// Build a Builtin.Executor value from an "complex equality" serial executor
10081013
/// reference.
10091014
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildComplexEqualitySerialExecutorRef,

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ PROTOCOL(FixedWidthInteger)
8686
PROTOCOL(RangeReplaceableCollection)
8787
PROTOCOL(Executor)
8888
PROTOCOL(SerialExecutor)
89+
PROTOCOL(TaskExecutor)
8990
PROTOCOL(GlobalActor)
9091

9192
PROTOCOL_(BridgedNSError)

include/swift/AST/KnownSDKTypes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ KNOWN_SDK_TYPE_DECL(Concurrency, Job, StructDecl, 0) // TODO: remove in favor of
4444
KNOWN_SDK_TYPE_DECL(Concurrency, ExecutorJob, StructDecl, 0)
4545
KNOWN_SDK_TYPE_DECL(Concurrency, UnownedJob, StructDecl, 0)
4646
KNOWN_SDK_TYPE_DECL(Concurrency, Executor, NominalTypeDecl, 0)
47+
KNOWN_SDK_TYPE_DECL(Concurrency, TaskExecutor, NominalTypeDecl, 0)
4748
KNOWN_SDK_TYPE_DECL(Concurrency, SerialExecutor, NominalTypeDecl, 0)
4849
KNOWN_SDK_TYPE_DECL(Concurrency, UnownedSerialExecutor, NominalTypeDecl, 0)
4950

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ LANGUAGE_FEATURE(BuiltinTaskGroupWithArgument, 0, "TaskGroup builtins", true)
8383
LANGUAGE_FEATURE(InheritActorContext, 0, "@_inheritActorContext attribute", true)
8484
LANGUAGE_FEATURE(ImplicitSelfCapture, 0, "@_implicitSelfCapture attribute", true)
8585
LANGUAGE_FEATURE(BuiltinBuildExecutor, 0, "Executor-building builtins", true)
86+
LANGUAGE_FEATURE(BuiltinBuildTaskExecutor, 0, "TaskExecutor-building builtins", true)
8687
LANGUAGE_FEATURE(BuiltinBuildComplexEqualityExecutor, 0, "Executor-building for 'complexEquality executor' builtins", true)
8788
LANGUAGE_FEATURE(BuiltinBuildMainExecutor, 0, "MainActor executor building builtin", true)
8889
LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroup, 0, "MainActor executor building builtin", true)

include/swift/Demangling/StandardTypesMangling.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ STANDARD_TYPE_CONCURRENCY(Protocol, F, Executor)
8888
STANDARD_TYPE_CONCURRENCY(Protocol, f, SerialExecutor)
8989
STANDARD_TYPE_CONCURRENCY(Structure, G, TaskGroup)
9090
STANDARD_TYPE_CONCURRENCY(Structure, g, ThrowingTaskGroup)
91+
STANDARD_TYPE_CONCURRENCY(Protocol, h, TaskExecutor)
9192
STANDARD_TYPE_CONCURRENCY(Protocol, I, AsyncIteratorProtocol)
9293
STANDARD_TYPE_CONCURRENCY(Protocol, i, AsyncSequence)
9394
STANDARD_TYPE_CONCURRENCY(Structure, J, UnownedJob)

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,7 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
11401140
case KnownProtocolKind::AsyncSequence:
11411141
case KnownProtocolKind::AsyncIteratorProtocol:
11421142
case KnownProtocolKind::Executor:
1143+
case KnownProtocolKind::TaskExecutor:
11431144
case KnownProtocolKind::SerialExecutor:
11441145
M = getLoadedModule(Id_Concurrency);
11451146
break;

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,6 +3086,10 @@ static bool usesFeatureBuiltinExecutor(Decl *decl) {
30863086
return usesBuiltinType(decl, BuiltinTypeKind::BuiltinExecutor);
30873087
}
30883088

3089+
static bool usesFeatureBuiltinBuildTaskExecutor(Decl *decl) {
3090+
return false;
3091+
}
3092+
30893093
static bool usesFeatureBuiltinBuildExecutor(Decl *decl) {
30903094
return false;
30913095
}

lib/AST/Builtins.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,16 @@ static ValueDecl *getTargetOSVersionAtLeast(ASTContext &Context,
16101610
return getBuiltinFunction(Id, {int32Type, int32Type, int32Type}, int32Type);
16111611
}
16121612

1613+
static ValueDecl *getBuildOrdinaryTaskExecutorRef(ASTContext &ctx,
1614+
Identifier id) {
1615+
return getBuiltinFunction(ctx, id, _thin,
1616+
_generics(_unrestricted,
1617+
_conformsTo(_typeparam(0), _taskExecutor)),
1618+
_parameters(_typeparam(0)),
1619+
_executor);
1620+
}
1621+
1622+
16131623
static ValueDecl *getBuildOrdinarySerialExecutorRef(ASTContext &ctx,
16141624
Identifier id) {
16151625
return getBuiltinFunction(ctx, id, _thin,
@@ -2919,6 +2929,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
29192929
case BuiltinValueKind::BuildComplexEqualitySerialExecutorRef:
29202930
return getBuildComplexEqualitySerialExecutorRef(Context, Id);
29212931

2932+
case BuiltinValueKind::BuildOrdinaryTaskExecutorRef:
2933+
return getBuildOrdinaryTaskExecutorRef(Context, Id);
2934+
29222935
case BuiltinValueKind::PoundAssert:
29232936
return getPoundAssert(Context, Id);
29242937

0 commit comments

Comments
 (0)