Skip to content

Commit a005f45

Browse files
authored
Merge pull request #41567 from rjmccall/remove-async-context-flags
Remove the Flags field from AsyncContext
2 parents 9e4ba44 + aca744b commit a005f45

File tree

12 files changed

+78
-134
lines changed

12 files changed

+78
-134
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,57 +2201,6 @@ class TaskOptionRecordFlags : public FlagSet<size_t> {
22012201
getKind, setKind)
22022202
};
22032203

2204-
/// Kinds of async context.
2205-
enum class AsyncContextKind {
2206-
/// An ordinary asynchronous function.
2207-
Ordinary = 0,
2208-
2209-
/// A context which can yield to its caller.
2210-
Yielding = 1,
2211-
2212-
/// A continuation context.
2213-
Continuation = 2,
2214-
2215-
// Other kinds are reserved for interesting special
2216-
// intermediate contexts.
2217-
2218-
// Kinds >= 192 are private to the implementation.
2219-
First_Reserved = 192
2220-
};
2221-
2222-
/// Flags for async contexts.
2223-
class AsyncContextFlags : public FlagSet<uint32_t> {
2224-
public:
2225-
enum {
2226-
Kind = 0,
2227-
Kind_width = 8,
2228-
2229-
CanThrow = 8,
2230-
2231-
// Kind-specific flags should grow down from 31.
2232-
2233-
Continuation_IsExecutorSwitchForced = 31,
2234-
};
2235-
2236-
explicit AsyncContextFlags(uint32_t bits) : FlagSet(bits) {}
2237-
constexpr AsyncContextFlags() {}
2238-
AsyncContextFlags(AsyncContextKind kind) {
2239-
setKind(kind);
2240-
}
2241-
2242-
/// The kind of context this represents.
2243-
FLAGSET_DEFINE_FIELD_ACCESSORS(Kind, Kind_width, AsyncContextKind,
2244-
getKind, setKind)
2245-
2246-
/// Whether this context is permitted to throw.
2247-
FLAGSET_DEFINE_FLAG_ACCESSORS(CanThrow, canThrow, setCanThrow)
2248-
2249-
/// See AsyncContinuationFlags::isExecutorSwitchForced.
2250-
FLAGSET_DEFINE_FLAG_ACCESSORS(Continuation_IsExecutorSwitchForced,
2251-
continuation_isExecutorSwitchForced,
2252-
continuation_setIsExecutorSwitchForced)
2253-
};
2254-
22552204
/// Flags passed to swift_continuation_init.
22562205
class AsyncContinuationFlags : public FlagSet<size_t> {
22572206
public:

include/swift/ABI/Task.h

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -631,19 +631,9 @@ class alignas(MaximumAlignment) AsyncContext {
631631
TaskContinuationFunction * __ptrauth_swift_async_context_resume
632632
ResumeParent;
633633

634-
/// Flags describing this context.
635-
///
636-
/// Note that this field is only 32 bits; any alignment padding
637-
/// following this on 64-bit platforms can be freely used by the
638-
/// function. If the function is a yielding function, that padding
639-
/// is of course interrupted by the YieldToParent field.
640-
AsyncContextFlags Flags;
641-
642-
AsyncContext(AsyncContextFlags flags,
643-
TaskContinuationFunction *resumeParent,
634+
AsyncContext(TaskContinuationFunction *resumeParent,
644635
AsyncContext *parent)
645-
: Parent(parent), ResumeParent(resumeParent),
646-
Flags(flags) {}
636+
: Parent(parent), ResumeParent(resumeParent) {}
647637

648638
AsyncContext(const AsyncContext &) = delete;
649639
AsyncContext &operator=(const AsyncContext &) = delete;
@@ -667,48 +657,66 @@ class YieldingAsyncContext : public AsyncContext {
667657
TaskContinuationFunction * __ptrauth_swift_async_context_yield
668658
YieldToParent;
669659

670-
YieldingAsyncContext(AsyncContextFlags flags,
671-
TaskContinuationFunction *resumeParent,
660+
YieldingAsyncContext(TaskContinuationFunction *resumeParent,
672661
TaskContinuationFunction *yieldToParent,
673662
AsyncContext *parent)
674-
: AsyncContext(flags, resumeParent, parent),
663+
: AsyncContext(resumeParent, parent),
675664
YieldToParent(yieldToParent) {}
676-
677-
static bool classof(const AsyncContext *context) {
678-
return context->Flags.getKind() == AsyncContextKind::Yielding;
679-
}
680665
};
681666

682667
/// An async context that can be resumed as a continuation.
683668
class ContinuationAsyncContext : public AsyncContext {
684669
public:
670+
class FlagsType : public FlagSet<size_t> {
671+
public:
672+
enum {
673+
CanThrow = 0,
674+
IsExecutorSwitchForced = 1,
675+
};
676+
677+
explicit FlagsType(size_t bits) : FlagSet(bits) {}
678+
constexpr FlagsType() {}
679+
680+
/// Whether this is a throwing continuation.
681+
FLAGSET_DEFINE_FLAG_ACCESSORS(CanThrow,
682+
canThrow,
683+
setCanThrow)
684+
685+
/// See AsyncContinuationFlags::isExecutorSwitchForced().
686+
FLAGSET_DEFINE_FLAG_ACCESSORS(IsExecutorSwitchForced,
687+
isExecutorSwitchForced,
688+
setIsExecutorSwitchForced)
689+
};
690+
691+
/// Flags for the continuation. Not public ABI.
692+
FlagsType Flags;
693+
685694
/// An atomic object used to ensure that a continuation is not
686695
/// scheduled immediately during a resume if it hasn't yet been
687-
/// awaited by the function which set it up.
696+
/// awaited by the function which set it up. Not public ABI.
688697
std::atomic<ContinuationStatus> AwaitSynchronization;
689698

690699
/// The error result value of the continuation.
691700
/// This should be null-initialized when setting up the continuation.
692701
/// Throwing resumers must overwrite this with a non-null value.
702+
/// Public ABI.
693703
SwiftError *ErrorResult;
694704

695705
/// A pointer to the normal result value of the continuation.
696706
/// Normal resumers must initialize this before resuming.
707+
/// Public ABI.
697708
OpaqueValue *NormalResult;
698709

699710
/// The executor that should be resumed to.
711+
/// Public ABI.
700712
ExecutorRef ResumeToExecutor;
701713

702714
void setErrorResult(SwiftError *error) {
703715
ErrorResult = error;
704716
}
705717

706718
bool isExecutorSwitchForced() const {
707-
return Flags.continuation_isExecutorSwitchForced();
708-
}
709-
710-
static bool classof(const AsyncContext *context) {
711-
return context->Flags.getKind() == AsyncContextKind::Continuation;
719+
return Flags.isExecutorSwitchForced();
712720
}
713721
};
714722

include/swift/Reflection/RuntimeInternals.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ template <typename Runtime>
131131
struct AsyncContext {
132132
typename Runtime::StoredSignedPointer Parent;
133133
typename Runtime::StoredSignedPointer ResumeParent;
134-
uint32_t Flags;
135134
};
136135

137136
template <typename Runtime>

lib/IRGen/GenCall.cpp

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ AsyncContextLayout irgen::getAsyncContextLayout(IRGenModule &IGM,
9393
}
9494

9595
static Size getAsyncContextHeaderSize(IRGenModule &IGM) {
96-
return 2 * IGM.getPointerSize() + Size(4);
96+
return 2 * IGM.getPointerSize();
9797
}
9898

9999
AsyncContextLayout irgen::getAsyncContextLayout(
@@ -123,19 +123,6 @@ AsyncContextLayout irgen::getAsyncContextLayout(
123123
typeInfos.push_back(&ti);
124124
}
125125

126-
// AsyncContextFlags Flags;
127-
// FIXME: this appears to be dead; we should adjust the layout of
128-
// the special async contexts that assume its existence and then
129-
// remove it.
130-
{
131-
auto ty = SILType::getPrimitiveObjectType(
132-
BuiltinIntegerType::get(32, IGM.IRGen.SIL.getASTContext())
133-
->getCanonicalType());
134-
const auto &ti = IGM.getTypeInfo(ty);
135-
valTypes.push_back(ty);
136-
typeInfos.push_back(&ti);
137-
}
138-
139126
return AsyncContextLayout(IGM, LayoutStrategy::Optimal, valTypes, typeInfos,
140127
originalType, substitutedType, substitutionMap);
141128
}
@@ -181,11 +168,7 @@ FunctionPointerKind::getStaticAsyncContextSize(IRGenModule &IGM) const {
181168
// If you add a new special runtime function, it is highly recommended
182169
// that you make calls to it allocate a little more memory than this!
183170
// These frames being this small is very arguably a mistake.
184-
//
185-
// FIXME: if we remove Flags in AsyncContextLayout (and thus from
186-
// headerSize), account for it here so that we continue to pass the
187-
// right amount of memory.
188-
return headerSize + 2 * IGM.getPointerSize();
171+
return headerSize + 3 * IGM.getPointerSize();
189172
}
190173
llvm_unreachable("covered switch");
191174
}

lib/IRGen/IRGenFunction.cpp

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,13 @@ static Address emitAddrOfContinuationNormalResultPointer(IRGenFunction &IGF,
575575
Address context) {
576576
assert(context.getType() == IGF.IGM.ContinuationAsyncContextPtrTy);
577577
auto offset = 5 * IGF.IGM.getPointerSize();
578+
return IGF.Builder.CreateStructGEP(context, 4, offset);
579+
}
580+
581+
static Address emitAddrOfContinuationErrorResultPointer(IRGenFunction &IGF,
582+
Address context) {
583+
assert(context.getType() == IGF.IGM.ContinuationAsyncContextPtrTy);
584+
auto offset = 4 * IGF.IGM.getPointerSize();
578585
return IGF.Builder.CreateStructGEP(context, 3, offset);
579586
}
580587

@@ -693,7 +700,8 @@ void IRGenFunction::emitAwaitAsyncContinuation(
693700
Explosion &outDirectResult, llvm::BasicBlock *&normalBB,
694701
llvm::PHINode *&optionalErrorResult, llvm::BasicBlock *&optionalErrorBB) {
695702
assert(AsyncCoroutineCurrentContinuationContext && "no active continuation");
696-
auto pointerAlignment = IGM.getPointerAlignment();
703+
Address continuationContext(AsyncCoroutineCurrentContinuationContext,
704+
IGM.getAsyncContextAlignment());
697705

698706
// Call swift_continuation_await to check whether the continuation
699707
// has already been resumed.
@@ -703,11 +711,9 @@ void IRGenFunction::emitAwaitAsyncContinuation(
703711
// swift_continuation_await, emit the old inline sequence. This can
704712
// be removed as soon as we're sure that such SDKs don't exist.
705713
if (!useContinuationAwait) {
706-
auto contAwaitSyncAddr = Builder.CreateStructGEP(
707-
AsyncCoroutineCurrentContinuationContext->getType()
708-
->getScalarType()
709-
->getPointerElementType(),
710-
AsyncCoroutineCurrentContinuationContext, 1);
714+
auto contAwaitSyncAddr =
715+
Builder.CreateStructGEP(continuationContext, 2,
716+
3 * IGM.getPointerSize()).getAddress();
711717

712718
auto pendingV = llvm::ConstantInt::get(
713719
contAwaitSyncAddr->getType()->getPointerElementType(),
@@ -759,11 +765,11 @@ void IRGenFunction::emitAwaitAsyncContinuation(
759765
Builder.CreateBitOrPointerCast(awaitFnPtr, IGM.Int8PtrTy));
760766

761767
if (useContinuationAwait) {
762-
arguments.push_back(AsyncCoroutineCurrentContinuationContext);
768+
arguments.push_back(continuationContext.getAddress());
763769
} else {
764770
arguments.push_back(AsyncCoroutineCurrentResume);
765771
arguments.push_back(Builder.CreateBitOrPointerCast(
766-
AsyncCoroutineCurrentContinuationContext, IGM.Int8PtrTy));
772+
continuationContext.getAddress(), IGM.Int8PtrTy));
767773
}
768774

769775
auto resultTy =
@@ -777,12 +783,7 @@ void IRGenFunction::emitAwaitAsyncContinuation(
777783
if (optionalErrorBB) {
778784
auto normalContBB = createBasicBlock("await.async.normal");
779785
auto contErrResultAddr =
780-
Address(Builder.CreateStructGEP(
781-
AsyncCoroutineCurrentContinuationContext->getType()
782-
->getScalarType()
783-
->getPointerElementType(),
784-
AsyncCoroutineCurrentContinuationContext, 2),
785-
pointerAlignment);
786+
emitAddrOfContinuationErrorResultPointer(*this, continuationContext);
786787
auto errorRes = Builder.CreateLoad(contErrResultAddr);
787788
auto nullError = llvm::Constant::getNullValue(errorRes->getType());
788789
auto hasError = Builder.CreateICmpNE(errorRes, nullError);
@@ -795,13 +796,10 @@ void IRGenFunction::emitAwaitAsyncContinuation(
795796
// result slot, load from the temporary we created during
796797
// get_async_continuation.
797798
if (!isIndirectResult) {
798-
auto contResultAddrAddr = Builder.CreateStructGEP(
799-
AsyncCoroutineCurrentContinuationContext->getType()
800-
->getScalarType()
801-
->getPointerElementType(),
802-
AsyncCoroutineCurrentContinuationContext, 3);
799+
auto contResultAddrAddr =
800+
emitAddrOfContinuationNormalResultPointer(*this, continuationContext);
803801
auto resultAddrVal =
804-
Builder.CreateLoad(Address(contResultAddrAddr, pointerAlignment));
802+
Builder.CreateLoad(contResultAddrAddr);
805803
// Take the result.
806804
auto &resumeTI = cast<LoadableTypeInfo>(getTypeInfo(resumeTy));
807805
auto resultStorageTy = resumeTI.getStorageType();

lib/IRGen/IRGenModule.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -662,9 +662,8 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
662662
TaskContinuationFunctionPtrTy = TaskContinuationFunctionTy->getPointerTo();
663663

664664
SwiftContextTy->setBody({
665-
SwiftContextPtrTy, // Parent
666-
TaskContinuationFunctionPtrTy, // ResumeParent,
667-
SizeTy, // Flags
665+
SwiftContextPtrTy, // Parent
666+
TaskContinuationFunctionPtrTy, // ResumeParent
668667
});
669668

670669
AsyncTaskAndContextTy = createStructType(
@@ -674,6 +673,7 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
674673
ContinuationAsyncContextTy = createStructType(
675674
*this, "swift.continuation_context",
676675
{SwiftContextTy, // AsyncContext header
676+
SizeTy, // flags
677677
SizeTy, // await synchronization
678678
ErrorPtrTy, // error result pointer
679679
OpaquePtrTy, // normal result address

stdlib/public/Concurrency/Task.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ void NullaryContinuationJob::process(Job *_job) {
165165

166166
_swift_task_dealloc_specific(task, job);
167167

168-
auto *context = cast<ContinuationAsyncContext>(continuation->ResumeContext);
168+
auto *context =
169+
static_cast<ContinuationAsyncContext*>(continuation->ResumeContext);
169170

170171
context->setErrorResult(nullptr);
171172
swift_continuation_resume(continuation);
@@ -825,7 +826,6 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
825826
// as if they might be null, even though the only time they ever might
826827
// be is the final hop. Store a signed null instead.
827828
initialContext->Parent = nullptr;
828-
initialContext->Flags = AsyncContextKind::Ordinary;
829829

830830
concurrency::trace::task_create(task, parent, group, asyncLet);
831831

@@ -1026,13 +1026,13 @@ swift_task_enqueueTaskOnExecutorImpl(AsyncTask *task, ExecutorRef executor)
10261026
SWIFT_CC(swift)
10271027
static AsyncTask *swift_continuation_initImpl(ContinuationAsyncContext *context,
10281028
AsyncContinuationFlags flags) {
1029-
context->Flags = AsyncContextKind::Continuation;
1029+
context->Flags = ContinuationAsyncContext::FlagsType();
10301030
if (flags.canThrow()) context->Flags.setCanThrow(true);
10311031
if (flags.isExecutorSwitchForced())
1032-
context->Flags.continuation_setIsExecutorSwitchForced(true);
1032+
context->Flags.setIsExecutorSwitchForced(true);
10331033
context->ErrorResult = nullptr;
10341034

1035-
// Set the current executor as the target executor unless there's
1035+
// Set the generic executor as the target executor unless there's
10361036
// an executor override.
10371037
if (!flags.hasExecutorOverride())
10381038
context->ResumeToExecutor = ExecutorRef::generic();
@@ -1156,21 +1156,21 @@ static void resumeTaskAfterContinuation(AsyncTask *task,
11561156

11571157
SWIFT_CC(swift)
11581158
static void swift_continuation_resumeImpl(AsyncTask *task) {
1159-
auto context = cast<ContinuationAsyncContext>(task->ResumeContext);
1159+
auto context = static_cast<ContinuationAsyncContext*>(task->ResumeContext);
11601160
resumeTaskAfterContinuation(task, context);
11611161
}
11621162

11631163
SWIFT_CC(swift)
11641164
static void swift_continuation_throwingResumeImpl(AsyncTask *task) {
1165-
auto context = cast<ContinuationAsyncContext>(task->ResumeContext);
1165+
auto context = static_cast<ContinuationAsyncContext*>(task->ResumeContext);
11661166
resumeTaskAfterContinuation(task, context);
11671167
}
11681168

11691169

11701170
SWIFT_CC(swift)
11711171
static void swift_continuation_throwingResumeWithErrorImpl(AsyncTask *task,
11721172
/* +1 */ SwiftError *error) {
1173-
auto context = cast<ContinuationAsyncContext>(task->ResumeContext);
1173+
auto context = static_cast<ContinuationAsyncContext*>(task->ResumeContext);
11741174
context->ErrorResult = error;
11751175
resumeTaskAfterContinuation(task, context);
11761176
}

stdlib/public/Concurrency/TaskPrivate.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,16 @@ namespace {
145145
///
146146
class TaskFutureWaitAsyncContext : public AsyncContext {
147147
public:
148+
// The ABI reserves three words of storage for these contexts, which
149+
// we currently use as follows. These fields are not accessed by
150+
// generated code; they're purely internal to the runtime, and only
151+
// when the calling task actually suspends.
152+
//
153+
// (If you think three words is an odd choice, one of them used to be
154+
// the context flags.)
148155
SwiftError *errorResult;
149-
150156
OpaqueValue *successResultPointer;
157+
void *_reserved;
151158

152159
void fillWithSuccess(AsyncTask::FutureFragment *future) {
153160
fillWithSuccess(future->getStoragePtr(), future->getResultType(),

0 commit comments

Comments
 (0)