Skip to content

Commit b5be7ee

Browse files
committed
work in progress on task names
1 parent 610d07e commit b5be7ee

23 files changed

+571
-31
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2719,6 +2719,7 @@ class JobFlags : public FlagSet<uint32_t> {
27192719
// 27 is currently unused
27202720
Task_IsAsyncLetTask = 28,
27212721
Task_HasInitialTaskExecutorPreference = 29,
2722+
Task_HasInitialTaskName = 30,
27222723
};
27232724
// clang-format on
27242725

@@ -2755,6 +2756,9 @@ class JobFlags : public FlagSet<uint32_t> {
27552756
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskExecutorPreference,
27562757
task_hasInitialTaskExecutorPreference,
27572758
task_setHasInitialTaskExecutorPreference)
2759+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_HasInitialTaskName,
2760+
task_hasInitialTaskName,
2761+
task_setHasInitialTaskName)
27582762
};
27592763

27602764
/// Kinds of task status record.
@@ -2784,6 +2788,9 @@ enum class TaskStatusRecordKind : uint8_t {
27842788
/// enqueued on.
27852789
TaskExecutorPreference = 5,
27862790

2791+
/// A human-readable task name.
2792+
TaskName = 6,
2793+
27872794
// Kinds >= 192 are private to the implementation.
27882795
First_Reserved = 192,
27892796
Private_RecordLock = 192
@@ -2807,6 +2814,8 @@ enum class TaskOptionRecordKind : uint8_t {
28072814
/// Set the initial task executor preference of the task.
28082815
InitialTaskExecutorUnowned = 5,
28092816
InitialTaskExecutorOwned = 6,
2817+
// Set a human-readable task name.
2818+
InitialTaskName = 7,
28102819
/// Request a child task for swift_task_run_inline.
28112820
RunInline = UINT8_MAX,
28122821
};

include/swift/ABI/Task.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,26 @@ class AsyncTask : public Job {
421421
/// Checking this is, of course, inherently race-prone on its own.
422422
bool isCancelled() const;
423423

424+
// ==== INITIAL TASK RECORDS =================================================
425+
// A task may have a number of "initial" records set, they MUST be set in the
426+
// following order to make the task-local allocation/deallocation's stack
427+
// discipline easy to work out at the tasks destruction:
428+
//
429+
// - Initial TaskName
430+
// - Initial ExecutorPreference
431+
432+
// ==== Task Naming ----------------------------------------------------------
433+
434+
/// At task creation a task may be assigned a name.
435+
void pushInitialTaskName(const char* taskName);
436+
void dropInitialTaskNameRecord();
437+
438+
const char* getTaskName();
439+
440+
bool hasInitialTaskName() const {
441+
return Flags.task_hasInitialTaskName();
442+
}
443+
424444
// ==== Task Executor Preference ---------------------------------------------
425445

426446
/// Get the preferred task executor reference if there is one set for this

include/swift/ABI/TaskOptions.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,26 @@ class InitialTaskExecutorOwnedPreferenceTaskOptionRecord
131131
}
132132
};
133133

134+
class InitialTaskNameTaskOptionRecord
135+
: public TaskOptionRecord {
136+
137+
const char* TaskName;
138+
139+
public:
140+
InitialTaskNameTaskOptionRecord(
141+
const char* taskName)
142+
: TaskOptionRecord(TaskOptionRecordKind::InitialTaskName),
143+
TaskName(taskName) {}
144+
145+
const char* getTaskName() const {
146+
return TaskName;
147+
}
148+
149+
static bool classof(const TaskOptionRecord *record) {
150+
return record->getKind() == TaskOptionRecordKind::InitialTaskName;
151+
}
152+
};
153+
134154
/// Task option to specify the initial serial executor for the task.
135155
class InitialSerialExecutorTaskOptionRecord : public TaskOptionRecord {
136156
const SerialExecutorRef Executor;

include/swift/ABI/TaskStatus.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,22 @@ class TaskExecutorPreferenceStatusRecord : public TaskStatusRecord {
320320
}
321321
};
322322

323+
class TaskNameStatusRecord : public TaskStatusRecord {
324+
private:
325+
const char *Name;
326+
327+
public:
328+
TaskNameStatusRecord(const char *name)
329+
: TaskStatusRecord(TaskStatusRecordKind::TaskName),
330+
Name(name) {}
331+
332+
const char *getName() { return Name; }
333+
334+
static bool classof(const TaskStatusRecord *record) {
335+
return record->getKind() == TaskStatusRecordKind::TaskName;
336+
}
337+
};
338+
323339
// This record is allocated for a task to record what it is dependent on before
324340
// the task can make progress again.
325341
class TaskDependencyStatusRecord : public TaskStatusRecord {

include/swift/AST/ASTSynthesis.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ enum SingletonTypeSynthesizer {
5757
_taskExecutor, // the '_Concurrency.TaskExecutor' protocol
5858
_actor, // the '_Concurrency.Actor' protocol
5959
_distributedActor, // the 'Distributed.DistributedActor' protocol
60+
_unsafeRawBufferPointer // UnsafeRawBufferPointer
6061
};
6162
inline Type synthesizeType(SynthesisContext &SC,
6263
SingletonTypeSynthesizer kind) {
@@ -89,6 +90,8 @@ inline Type synthesizeType(SynthesisContext &SC,
8990
case _distributedActor:
9091
return SC.Context.getProtocol(KnownProtocolKind::DistributedActor)
9192
->getDeclaredInterfaceType();
93+
case _unsafeRawBufferPointer:
94+
return SC.Context.getUnsafeRawBufferPointerType();
9295
case _copyable:
9396
return SC.Context.getProtocol(KnownProtocolKind::Copyable)
9497
->getDeclaredInterfaceType();

include/swift/AST/Builtins.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,9 @@ BUILTIN_MISC_OPERATION(UnprotectedAddressOfBorrowOpaque, "unprotectedAddressOfBo
952952
/// createTask<T>(flags: Int,
953953
/// initialSerialExecutor: (Builtin.Executor)? = nil,
954954
/// taskGroup: Builtin.RawPointer? = nil,
955-
/// initialTaskExecutor: (Builtin.Executor)? = nil,
955+
/// initialTaskExecutorDeprecated: (Builtin.Executor)? = nil,
956+
/// initialTaskExecutorOwned: (any TaskExecutor)? = nil,
957+
/// taskName: UnsafeRawBufferPointer? = nil,
956958
/// operation: sending @escaping () async throws -> T)
957959
/// -> Builtin.NativeObject, Builtin.RawPointer)
958960
///

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ BASELINE_LANGUAGE_FEATURE(BuiltinBuildExecutor, 0, "Executor-building builtins")
151151
BASELINE_LANGUAGE_FEATURE(BuiltinBuildComplexEqualityExecutor, 0, "Executor-building for 'complexEquality executor' builtins")
152152
BASELINE_LANGUAGE_FEATURE(BuiltinBuildMainExecutor, 0, "MainActor executor building builtin")
153153
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskOwnedTaskExecutor, 0, "Task create with owned TaskExecutor")
154+
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskName, 0, "Task create with a name")
154155
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroup, 0, "Task create in task group builtin with extra flags")
155156
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroupWithExecutor, 0, "Task create in task group builtin with extra flags")
156157
BASELINE_LANGUAGE_FEATURE(BuiltinCreateAsyncDiscardingTaskInGroup, 0, "Task create in discarding task group builtin, accounting for the Void return type")

include/swift/Runtime/Concurrency.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,9 @@ void swift_task_reportUnexpectedExecutor(
10101010
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
10111011
JobPriority swift_task_getCurrentThreadPriority(void);
10121012

1013+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
1014+
const char *swift_task_getCurrentTaskName(void);
1015+
10131016
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
10141017
void swift_task_startOnMainActor(AsyncTask* job);
10151018

lib/AST/Builtins.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,19 @@ _generics(ParamS... params) {
219219
return {{params...}};
220220
}
221221

222+
///// A conditional synthesizer which generates a generic parameter list.
223+
///// If the 'condition' is false, no generic parameters are created.
224+
//template <class... ParamS>
225+
//struct ConditionalGenericParamListSynthesizer {
226+
// bool condition;
227+
// VariadicSynthesizerStorage<ParamS...> Params;
228+
//};
229+
//template <class... ParamS>
230+
//constexpr ConditionalGenericParamListSynthesizer<ParamS...>
231+
//_ifGenerics(bool condition, ParamS... params) {
232+
// return {condition, {params...}};
233+
//}
234+
222235
struct CountGenericParameters {
223236
unsigned &Count;
224237

@@ -292,6 +305,21 @@ static GenericParamList *synthesizeGenericParamList(SynthesisContext &SC,
292305
return paramList;
293306
}
294307

308+
//template <class... ParamsS>
309+
//static GenericParamList *synthesizeGenericParamList(
310+
// SynthesisContext &SC,
311+
// const ConditionalGenericParamListSynthesizer<ParamsS...> &params) {
312+
// if (params.condition) {
313+
// unsigned count = 0;
314+
// params.Params.visit(CountGenericParameters{count});
315+
// auto paramList = getGenericParams(SC.Context, count);
316+
// SC.GenericParams = paramList;
317+
// return paramList;
318+
// } else {
319+
// return GenericParamList::create(SC.Context, SourceLoc(), {}, SourceLoc());
320+
// }
321+
//}
322+
295323
namespace {
296324
struct CollectGenericParams {
297325
SynthesisContext &SC;
@@ -341,6 +369,24 @@ synthesizeGenericSignature(SynthesisContext &SC,
341369
/*allowInverses=*/false);
342370
}
343371

372+
//template <class... ParamsS>
373+
//static GenericSignature
374+
//synthesizeGenericSignature(SynthesisContext &SC,
375+
// const ConditionalGenericParamListSynthesizer<ParamsS...> &list) {
376+
// CollectGenericParams collector(SC);
377+
// if (list.condition) {
378+
// list.Params.visit(collector);
379+
//
380+
// return buildGenericSignature(SC.Context,
381+
// GenericSignature(),
382+
// std::move(collector.GenericParamTypes),
383+
// std::move(collector.AddedRequirements),
384+
// /*allowInverses=*/false);
385+
// } else {
386+
// return GenericSignature();
387+
// }
388+
//}
389+
344390
/// Build a builtin function declaration.
345391
///
346392
/// This is a "legacy" interface; you should probably use one of
@@ -1553,7 +1599,35 @@ Type swift::getAsyncTaskAndContextType(ASTContext &ctx) {
15531599
return TupleType::get(resultTupleElements, ctx);
15541600
}
15551601

1602+
//static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id, bool isDiscarding) {
1603+
// auto taskExecutorIsAvailable =
1604+
// ctx.getProtocol(swift::KnownProtocolKind::TaskExecutor) != nullptr;
1605+
//
1606+
// return getBuiltinFunction(
1607+
// ctx, id, _thin, _ifGenerics(/*if=*/isDiscarding,
1608+
// _unrestricted, _conformsToDefaults(0)),
1609+
// _parameters(
1610+
// _label("flags", _swiftInt),
1611+
// _label("initialSerialExecutor",
1612+
// _defaulted(_optional(_executor), _nil)),
1613+
// _label("taskGroup", _defaulted(_optional(_rawPointer), _nil)),
1614+
// _label("initialTaskExecutor", _defaulted(_optional(_executor), _nil)),
1615+
// _label("initialTaskExecutorConsuming",
1616+
// _defaulted(_consuming(_optional(_bincompatType(
1617+
// /*if=*/taskExecutorIsAvailable,
1618+
// _existential(_taskExecutor),
1619+
// /*else=*/_executor))),
1620+
// _nil)),
1621+
// _label("taskName", _defaulted(_optional(_unsafeRawBufferPointer), _nil)),
1622+
// _label("operation",
1623+
// _sending(_function(_async(_throws(_thick)), _typeparam(0),
1624+
// _parameters())))),
1625+
// _tuple(_nativeObject, _rawPointer));
1626+
//}
1627+
15561628
static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) {
1629+
// return getCreateTask(ctx, id, /*isDiscarding=*/false);
1630+
15571631
auto taskExecutorIsAvailable =
15581632
ctx.getProtocol(swift::KnownProtocolKind::TaskExecutor) != nullptr;
15591633

@@ -1571,6 +1645,7 @@ static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) {
15711645
_existential(_taskExecutor),
15721646
/*else*/ _executor))),
15731647
_nil)),
1648+
_label("taskName", _defaulted(_optional(_unsafeRawBufferPointer), _nil)),
15741649
_label("operation",
15751650
_sending(_function(_async(_throws(_thick)), _typeparam(0),
15761651
_parameters())))),
@@ -1595,6 +1670,7 @@ static ValueDecl *getCreateDiscardingTask(ASTContext &ctx, Identifier id) {
15951670
_existential(_taskExecutor),
15961671
/*else*/ _executor))),
15971672
_nil)),
1673+
_label("taskName", _defaulted(_optional(_unsafeRawBufferPointer), _nil)),
15981674
_label("operation", _sending(_function(_async(_throws(_thick)), _void,
15991675
_parameters())))),
16001676
_tuple(_nativeObject, _rawPointer));

lib/IRGen/GenConcurrency.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,9 +686,10 @@ struct TaskGroupRecordTraits {
686686

687687
void initialize(IRGenFunction &IGF, Address recordAddr,
688688
Explosion &taskGroup) const {
689+
auto record = IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
689690
IGF.Builder.CreateStore(
690691
taskGroup.claimNext(),
691-
IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize()));
692+
record);
692693
}
693694
};
694695

@@ -747,6 +748,55 @@ struct InitialTaskExecutorOwnedRecordTraits {
747748
}
748749
};
749750

751+
struct InitialTaskNameRecordTraits {
752+
static StringRef getLabel() {
753+
return "task_name";
754+
}
755+
static llvm::StructType *getRecordType(IRGenModule &IGM) {
756+
return IGM.SwiftInitialTaskNameTaskOptionRecordTy;
757+
}
758+
static TaskOptionRecordFlags getRecordFlags() {
759+
return TaskOptionRecordFlags(TaskOptionRecordKind::InitialTaskName);
760+
}
761+
static CanType getValueType(ASTContext &ctx) {
762+
// FIXME: maybe raw pointer type?
763+
return OptionalType::get(ctx.getUnsafeRawBufferPointerType())
764+
->getCanonicalType();
765+
}
766+
767+
// Create 'InitialTaskNameTaskOptionRecord'
768+
void initialize(IRGenFunction &IGF, Address recordAddr,
769+
Explosion &taskName) const {
770+
771+
fprintf(stderr, "[%s:%d](%s) initialize InitialTaskNameTaskOptionRecord\n", __FILE_NAME__, __LINE__, __FUNCTION__);
772+
taskName.dump();
773+
774+
fprintf(stderr, "[%s:%d](%s) taskName.size() = %d\n", __FILE_NAME__, __LINE__, __FUNCTION__,
775+
taskName.size());
776+
777+
// FIXME: why is this wrong?
778+
// [GenConcurrency.cpp:725](initialize) initialize InitialTaskNameTaskOptionRecord
779+
// %16 = extractvalue { i64, i64 } %15, 0
780+
// %17 = extractvalue { i64, i64 } %15, 1
781+
// [GenConcurrency.cpp:728](initialize) taskName.size() = 2
782+
// Assertion failed: (isa<llvm::StructType>(address.getElementType()) || isa<llvm::ArrayType>(address.getElementType())), function CreateStructGEP, file IRBuilder.h, line 193. Process 27213 stopped
783+
784+
// auto record =
785+
// IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
786+
// IGF.Builder.CreateStore(taskName.claimNext(),
787+
// IGF.Builder.CreateStructGEP(record, 0, Size()));
788+
// IGF.Builder.CreateStore(taskName.claimNext(),
789+
// IGF.Builder.CreateStructGEP(record, 1, Size()));
790+
791+
auto record = IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
792+
fprintf(stderr, "[%s:%d](%s) record = \n", __FILE_NAME__, __LINE__, __FUNCTION__);
793+
record->dump();
794+
IGF.Builder.CreateStore(
795+
taskName.claimNext(),
796+
record);
797+
}
798+
};
799+
750800
} // end anonymous namespace
751801

752802
static llvm::Value *
@@ -783,12 +833,20 @@ maybeAddInitialTaskExecutorOwnedOptionRecord(IRGenFunction &IGF,
783833
taskExecutorExistential);
784834
}
785835

836+
static llvm::Value *
837+
maybeAddTaskNameOptionRecord(IRGenFunction &IGF, llvm::Value *prevOptions,
838+
OptionalExplosion &taskName) {
839+
return maybeAddOptionRecord(IGF, prevOptions, InitialTaskNameRecordTraits(),
840+
taskName);
841+
}
842+
786843
std::pair<llvm::Value *, llvm::Value *>
787844
irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
788845
OptionalExplosion &serialExecutor,
789846
OptionalExplosion &taskGroup,
790847
OptionalExplosion &taskExecutorUnowned,
791848
OptionalExplosion &taskExecutorExistential,
849+
OptionalExplosion &taskName,
792850
Explosion &taskFunction,
793851
SubstitutionMap subs) {
794852
llvm::Value *taskOptions =
@@ -825,6 +883,16 @@ irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
825883
IGF, taskOptions, taskExecutorExistential);
826884
}
827885

886+
// Add an option record for the initial task name, if present.
887+
//
888+
// (lldb) e taskName.value.Values[0]
889+
// (llvm::Value *) $11 = 0x000060000220d1a0
890+
// (lldb) e taskName.value.Values[0]->dump()
891+
// %16 = extractvalue { i64, i64 } %15, 0
892+
// (lldb) e taskName.value.Values[1]->dump()
893+
// %17 = extractvalue { i64, i64 } %15, 1
894+
taskOptions = maybeAddTaskNameOptionRecord(IGF, taskOptions, taskName);
895+
828896
// In embedded Swift, create and pass result type info.
829897
taskOptions = maybeAddEmbeddedSwiftResultTypeInfo(IGF, taskOptions, resultType);
830898

lib/IRGen/GenConcurrency.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
106106
OptionalExplosion &taskGroup,
107107
OptionalExplosion &taskExecutorUnowned,
108108
OptionalExplosion &taskExecutorExistential,
109+
OptionalExplosion &taskName,
109110
Explosion &taskFunction,
110111
SubstitutionMap subs);
111112

0 commit comments

Comments
 (0)