Skip to content

Commit 3508865

Browse files
committed
[5.5] Change _wait(_throwing) ABIs to reduce code size
Changes the task, taskGroup, asyncLet wait funtion call ABIs. To reduce code size pass the context parameters and resumption function as arguments to the wait function. This means that the suspend point does not need to store parent context and resumption to the suspend point's context. ``` void swift_task_future_wait_throwing( OpaqueValue * result, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, AsyncTask *task, ThrowingTaskFutureWaitContinuationFunction *resume, AsyncContext *callContext); ``` The runtime passes the caller context to the resume entry point saving the load of the parent context in the resumption function. This patch adds a `Metadata *` field to `GroupImpl`. The await entry pointer no longer pass the metadata pointer and there is a path through the runtime where the task future is no longer available.
1 parent c6778c8 commit 3508865

26 files changed

+311
-271
lines changed

include/swift/ABI/Executor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ using TaskContinuationFunction =
128128
SWIFT_CC(swiftasync)
129129
void (SWIFT_ASYNC_CONTEXT AsyncContext *);
130130

131+
using ThrowingTaskFutureWaitContinuationFunction =
132+
SWIFT_CC(swiftasync)
133+
void (SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *);
134+
135+
131136
template <class AsyncSignature>
132137
class AsyncFunctionPointer;
133138
template <class AsyncSignature>

include/swift/Runtime/Concurrency.h

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,6 @@ swift_task_escalate(AsyncTask *task, JobPriority newPriority);
125125
// TODO: "async let wait" and "async let destroy" would be expressed
126126
// similar to like TaskFutureWait;
127127

128-
/// This matches the ABI of a closure `<T>(Builtin.NativeObject) async -> T`
129-
using TaskFutureWaitSignature =
130-
SWIFT_CC(swiftasync)
131-
void(OpaqueValue *,
132-
SWIFT_ASYNC_CONTEXT AsyncContext *, AsyncTask *, Metadata *);
133-
134128
/// Wait for a non-throwing future task to complete.
135129
///
136130
/// This can be called from any thread. Its Swift signature is
@@ -141,12 +135,9 @@ using TaskFutureWaitSignature =
141135
/// \endcode
142136
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
143137
void swift_task_future_wait(OpaqueValue *,
144-
SWIFT_ASYNC_CONTEXT AsyncContext *, AsyncTask *, Metadata *);
145-
146-
using TaskFutureWaitThrowingSignature =
147-
SWIFT_CC(swiftasync)
148-
void(OpaqueValue *,
149-
SWIFT_ASYNC_CONTEXT AsyncContext *, AsyncTask *, Metadata *);
138+
SWIFT_ASYNC_CONTEXT AsyncContext *, AsyncTask *,
139+
TaskContinuationFunction *,
140+
AsyncContext *);
150141

151142
/// Wait for a potentially-throwing future task to complete.
152143
///
@@ -157,15 +148,12 @@ using TaskFutureWaitThrowingSignature =
157148
/// async throws -> Success
158149
/// \endcode
159150
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
160-
void swift_task_future_wait_throwing(OpaqueValue *,
161-
SWIFT_ASYNC_CONTEXT AsyncContext *,
162-
AsyncTask *, Metadata *);
163-
164-
using TaskGroupFutureWaitThrowingSignature =
165-
SWIFT_CC(swiftasync)
166-
void(OpaqueValue *,
167-
SWIFT_ASYNC_CONTEXT AsyncContext *, AsyncTask *, TaskGroup *,
168-
const Metadata *successType);
151+
void swift_task_future_wait_throwing(
152+
OpaqueValue *,
153+
SWIFT_ASYNC_CONTEXT AsyncContext *,
154+
AsyncTask *,
155+
ThrowingTaskFutureWaitContinuationFunction *,
156+
AsyncContext *);
169157

170158
/// Wait for a readyQueue of a Channel to become non empty.
171159
///
@@ -180,8 +168,9 @@ SWIFT_CC(swiftasync)
180168
SWIFT_EXPORT_FROM(swift_Concurrency)
181169
SWIFT_CC(swiftasync)
182170
void swift_taskGroup_wait_next_throwing(
183-
OpaqueValue *resultPointer, SWIFT_ASYNC_CONTEXT AsyncContext *rawContext,
184-
TaskGroup *group, const Metadata *successType);
171+
OpaqueValue *resultPointer, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
172+
TaskGroup *group, ThrowingTaskFutureWaitContinuationFunction *resumeFn,
173+
AsyncContext *callContext);
185174

186175
/// Initialize a `TaskGroup` in the passed `group` memory location.
187176
/// The caller is responsible for retaining and managing the group's lifecycle.
@@ -192,7 +181,7 @@ void swift_taskGroup_wait_next_throwing(
192181
/// func swift_taskGroup_initialize(group: Builtin.RawPointer)
193182
/// \endcode
194183
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
195-
void swift_taskGroup_initialize(TaskGroup *group);
184+
void swift_taskGroup_initialize(TaskGroup *group, const Metadata *T);
196185

197186
/// Attach a child task to the parent task's task group record.
198187
///
@@ -310,7 +299,8 @@ using AsyncLetWaitSignature =
310299
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
311300
void swift_asyncLet_wait(OpaqueValue *,
312301
SWIFT_ASYNC_CONTEXT AsyncContext *,
313-
AsyncLet *, Metadata *);
302+
AsyncLet *, TaskContinuationFunction *,
303+
AsyncContext *);
314304

315305
/// Wait for a potentially-throwing async-let to complete.
316306
///
@@ -324,7 +314,9 @@ void swift_asyncLet_wait(OpaqueValue *,
324314
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
325315
void swift_asyncLet_wait_throwing(OpaqueValue *,
326316
SWIFT_ASYNC_CONTEXT AsyncContext *,
327-
AsyncLet *, Metadata *);
317+
AsyncLet *,
318+
ThrowingTaskFutureWaitContinuationFunction *,
319+
AsyncContext *);
328320

329321
/// Its Swift signature is
330322
///

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,7 @@ FUNCTION(TaskGroupInitialize,
17281728
swift_taskGroup_initialize, SwiftCC,
17291729
ConcurrencyAvailability,
17301730
RETURNS(VoidTy),
1731-
ARGS(Int8PtrTy),
1731+
ARGS(Int8PtrTy, TypeMetadataPtrTy),
17321732
ATTRS(NoUnwind))
17331733

17341734
// void swift_taskGroup_destroy(TaskGroup *group);

lib/AST/Builtins.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,8 @@ static ValueDecl *getEndAsyncLet(ASTContext &ctx, Identifier id) {
15151515

15161516
static ValueDecl *getCreateTaskGroup(ASTContext &ctx, Identifier id) {
15171517
return getBuiltinFunction(ctx, id, _thin,
1518-
_parameters(),
1518+
_generics(_unrestricted),
1519+
_parameters(_metatype(_typeparam(0))),
15191520
_rawPointer);
15201521
}
15211522

lib/IRGen/CallEmission.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ class CallEmission {
119119

120120
return result;
121121
}
122+
123+
virtual llvm::Value *getResumeFunctionPointer() = 0;
124+
virtual llvm::Value *getAsyncContext() = 0;
122125
};
123126

124127
std::unique_ptr<CallEmission>

lib/IRGen/Callee.h

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -209,24 +209,16 @@ namespace irgen {
209209
///
210210
/// This is a micro-optimization we apply to certain special functions
211211
/// that we know don't need generics.
212-
bool suppressGenerics() const {
212+
bool useSpecialConvention() const {
213213
if (!isSpecial()) return false;
214214

215215
switch (getSpecialKind()) {
216-
case SpecialKind::TaskFutureWait:
216+
case SpecialKind::AsyncLetWaitThrowing:
217217
case SpecialKind::TaskFutureWaitThrowing:
218+
case SpecialKind::TaskFutureWait:
218219
case SpecialKind::AsyncLetWait:
219-
case SpecialKind::AsyncLetWaitThrowing:
220220
case SpecialKind::TaskGroupWaitNext:
221-
// FIXME: I have disabled this optimization, if we bring it back we
222-
// need to debug why it currently does not work (call emission
223-
// computes an undef return pointer) and change the runtime entries to
224-
// remove the extra type parameter.
225-
//
226-
// We suppress generics from these as a code-size optimization
227-
// because the runtime can recover the success type from the
228-
// future.
229-
return false;
221+
return true;
230222
}
231223
}
232224

@@ -371,9 +363,7 @@ namespace irgen {
371363
return !kind.isAsyncFunctionPointer();
372364
}
373365

374-
bool suppressGenerics() const {
375-
return kind.suppressGenerics();
376-
}
366+
bool useSpecialConvention() const { return kind.useSpecialConvention(); }
377367
};
378368

379369
class Callee {
@@ -437,9 +427,7 @@ namespace irgen {
437427
return Fn.getSignature();
438428
}
439429

440-
bool suppressGenerics() const {
441-
return Fn.suppressGenerics();
442-
}
430+
bool useSpecialConvention() const { return Fn.useSpecialConvention(); }
443431

444432
/// If this callee has a value for the Swift context slot, return
445433
/// it; otherwise return non-null.
@@ -457,6 +445,7 @@ namespace irgen {
457445
llvm::Value *getObjCMethodSelector() const;
458446
};
459447

448+
FunctionPointer::Kind classifyFunctionPointerKind(SILFunction *fn);
460449
} // end namespace irgen
461450
} // end namespace swift
462451

lib/IRGen/GenBuiltin.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,9 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
250250
}
251251

252252
if (Builtin.ID == BuiltinValueKind::CreateTaskGroup) {
253-
out.add(emitCreateTaskGroup(IGF));
253+
// Claim metadata pointer.
254+
(void)args.claimAll();
255+
out.add(emitCreateTaskGroup(IGF, substitutions));
254256
return;
255257
}
256258

0 commit comments

Comments
 (0)