@@ -126,7 +126,7 @@ class alignas(2 * alignof(void*)) Job :
126
126
};
127
127
128
128
// The compiler will eventually assume these.
129
- #if defined(__LP64__) || defined(_WIN64)
129
+ #if SWIFT_POINTER_IS_8_BYTES
130
130
static_assert (sizeof (Job) == 6 * sizeof(void *),
131
131
"Job size is wrong");
132
132
#else
@@ -136,46 +136,6 @@ static_assert(sizeof(Job) == 8 * sizeof(void*),
136
136
static_assert (alignof (Job) == 2 * alignof (void *),
137
137
"Job alignment is wrong");
138
138
139
- // / The current state of a task's status records.
140
- class ActiveTaskStatus {
141
- enum : uintptr_t {
142
- IsCancelled = 0x1 ,
143
- IsLocked = 0x2 ,
144
- RecordMask = ~uintptr_t (IsCancelled | IsLocked)
145
- };
146
-
147
- uintptr_t Value;
148
-
149
- public:
150
- constexpr ActiveTaskStatus () : Value(0 ) {}
151
- ActiveTaskStatus (TaskStatusRecord *innermostRecord,
152
- bool cancelled, bool locked)
153
- : Value(reinterpret_cast <uintptr_t >(innermostRecord)
154
- + (locked ? IsLocked : 0 )
155
- + (cancelled ? IsCancelled : 0 )) {}
156
-
157
- // / Is the task currently cancelled?
158
- bool isCancelled () const { return Value & IsCancelled; }
159
-
160
- // / Is there an active lock on the cancellation information?
161
- bool isLocked () const { return Value & IsLocked; }
162
-
163
- // / Return the innermost cancellation record. Code running
164
- // / asynchronously with this task should not access this record
165
- // / without having first locked it; see swift_taskCancel.
166
- TaskStatusRecord *getInnermostRecord () const {
167
- return reinterpret_cast <TaskStatusRecord*>(Value & RecordMask);
168
- }
169
-
170
- static TaskStatusRecord *getStatusRecordParent (TaskStatusRecord *ptr);
171
-
172
- using record_iterator =
173
- LinkedListIterator<TaskStatusRecord, getStatusRecordParent>;
174
- llvm::iterator_range<record_iterator> records () const {
175
- return record_iterator::rangeBeginning (getInnermostRecord ());
176
- }
177
- };
178
-
179
139
class NullaryContinuationJob : public Job {
180
140
181
141
private:
@@ -212,6 +172,16 @@ class NullaryContinuationJob : public Job {
212
172
// / it can hold, and thus must be the *last* fragment.
213
173
class AsyncTask : public Job {
214
174
public:
175
+ // On 32-bit targets, there is a word of tail padding remaining
176
+ // in Job, and ResumeContext will fit into that, at offset 28.
177
+ // Private then has offset 32.
178
+ // On 64-bit targets, there is no tail padding in Job, and so
179
+ // ResumeContext has offset 48. There is therefore another word
180
+ // of reserved storage prior to Private (which needs to have
181
+ // double-word alignment), which has offset 64.
182
+ // We therefore converge and end up with 16 words of storage on
183
+ // all platforms.
184
+
215
185
// / The context for resuming the job. When a task is scheduled
216
186
// / as a job, the next continuation should be installed as the
217
187
// / ResumeTask pointer in the job header, with this serving as
@@ -222,36 +192,57 @@ class AsyncTask : public Job {
222
192
// / prevent it from being corrupted in flight.
223
193
AsyncContext * __ptrauth_swift_task_resume_context ResumeContext;
224
194
225
- // / The currently-active information about cancellation.
226
- std::atomic<ActiveTaskStatus> Status;
195
+ #if SWIFT_POINTER_IS_8_BYTES
196
+ void *Reserved64;
197
+ #endif
227
198
228
- // / Reserved for the use of the task-local stack allocator.
229
- void *AllocatorPrivate[4 ];
199
+ struct PrivateStorage ;
230
200
231
- // / Task local values storage container.
232
- TaskLocal::Storage Local;
201
+ // / Private storage for the use of the runtime.
202
+ struct alignas (2 * alignof (void *)) OpaquePrivateStorage {
203
+ void *Storage[8 ];
233
204
205
+ // / Initialize this storage during the creation of a task.
206
+ void initialize (AsyncTask *task);
207
+ void initializeWithSlab (AsyncTask *task,
208
+ void *slab, size_t slabCapacity);
209
+
210
+ // / React to the completion of the enclosing task's execution.
211
+ void complete (AsyncTask *task);
212
+
213
+ // / React to the final destruction of the enclosing task.
214
+ void destroy ();
215
+
216
+ PrivateStorage &get ();
217
+ const PrivateStorage &get () const ;
218
+ };
219
+ PrivateStorage &_private ();
220
+ const PrivateStorage &_private () const ;
221
+
222
+ OpaquePrivateStorage Private;
223
+
224
+ // / Create a task.
225
+ // / This does not initialize Private; callers must call
226
+ // / Private.initialize separately.
234
227
AsyncTask (const HeapMetadata *metadata, JobFlags flags,
235
228
TaskContinuationFunction *run,
236
229
AsyncContext *initialContext)
237
230
: Job(flags, run, metadata),
238
- ResumeContext (initialContext),
239
- Status(ActiveTaskStatus()),
240
- Local(TaskLocal::Storage()) {
231
+ ResumeContext (initialContext) {
241
232
assert (flags.isAsyncTask ());
242
233
Id = getNextTaskId ();
243
234
}
244
235
245
236
// / Create a task with "immortal" reference counts.
246
237
// / Used for async let tasks.
238
+ // / This does not initialize Private; callers must call
239
+ // / Private.initialize separately.
247
240
AsyncTask (const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
248
241
JobFlags flags,
249
242
TaskContinuationFunction *run,
250
243
AsyncContext *initialContext)
251
244
: Job(flags, run, metadata, immortal),
252
- ResumeContext(initialContext),
253
- Status(ActiveTaskStatus()),
254
- Local(TaskLocal::Storage()) {
245
+ ResumeContext(initialContext) {
255
246
assert (flags.isAsyncTask ());
256
247
Id = getNextTaskId ();
257
248
}
@@ -269,25 +260,18 @@ class AsyncTask : public Job {
269
260
270
261
// / Check whether this task has been cancelled.
271
262
// / Checking this is, of course, inherently race-prone on its own.
272
- bool isCancelled () const {
273
- return Status.load (std::memory_order_relaxed).isCancelled ();
274
- }
263
+ bool isCancelled () const ;
275
264
276
265
// ==== Task Local Values ----------------------------------------------------
277
266
278
267
void localValuePush (const HeapObject *key,
279
- /* +1 */ OpaqueValue *value, const Metadata *valueType) {
280
- Local.pushValue (this , key, value, valueType);
281
- }
268
+ /* +1 */ OpaqueValue *value,
269
+ const Metadata *valueType);
282
270
283
- OpaqueValue* localValueGet (const HeapObject *key) {
284
- return Local.getValue (this , key);
285
- }
271
+ OpaqueValue *localValueGet (const HeapObject *key);
286
272
287
273
// / Returns true if storage has still more bindings.
288
- bool localValuePop () {
289
- return Local.popValue (this );
290
- }
274
+ bool localValuePop ();
291
275
292
276
// ==== Child Fragment -------------------------------------------------------
293
277
@@ -529,7 +513,7 @@ class AsyncTask : public Job {
529
513
};
530
514
531
515
// The compiler will eventually assume these.
532
- static_assert (sizeof (AsyncTask) == 14 * sizeof(void *),
516
+ static_assert (sizeof (AsyncTask) == NumWords_AsyncTask * sizeof(void *),
533
517
"AsyncTask size is wrong");
534
518
static_assert (alignof (AsyncTask) == 2 * alignof(void *),
535
519
"AsyncTask alignment is wrong");
0 commit comments