@@ -181,7 +181,7 @@ void TaskLocal::Storage::initializeLinkParent(AsyncTask* task,
181181 if (!item)
182182 return ;
183183
184- auto tail = TaskLocal::ParentTaskMarkerItem::create (task);
184+ auto tail = TaskLocal::MarkerItem::createParentTaskMarker (task);
185185 head = tail;
186186
187187 // Set of keys for which we already have copied to the new task.
@@ -234,18 +234,24 @@ void TaskLocal::Storage::initializeLinkParent(AsyncTask* task,
234234 item = item->getNext ();
235235 }
236236
237+ if (item && item->getKind () == Item::Kind::StopLookupMarker) {
238+ // Stop marker also could have been created inside task group body
239+ // But we don't need to copy it. Instead we can break the chain.
240+ item = nullptr ;
241+ }
242+
237243 // The next item is not the "risky one" so we can directly link to it,
238244 // as we would have within normal child task relationships. E.g. this is
239245 // a parent or next pointer to a "safe" (withValue { withTaskGroup { ... } })
240246 // binding, so we re-link our current head to point at this item.
241247 tail->setNext (item);
242248}
243249
244- TaskLocal::ParentTaskMarkerItem *
245- TaskLocal::ParentTaskMarkerItem::create (AsyncTask *task ) {
246- size_t amountToAllocate = sizeof (ParentTaskMarkerItem );
250+ TaskLocal::MarkerItem * TaskLocal::MarkerItem::create (AsyncTask *task,
251+ Item *next, Kind kind ) {
252+ size_t amountToAllocate = sizeof (MarkerItem );
247253 void *allocation = _swift_task_alloc_specific (task, amountToAllocate);
248- return new (allocation) ParentTaskMarkerItem ( nullptr );
254+ return new (allocation) MarkerItem (next, kind );
249255}
250256
251257TaskLocal::ValueItem *TaskLocal::ValueItem::create (AsyncTask *task,
@@ -367,11 +373,12 @@ bool TaskLocal::Item::destroy(AsyncTask *task) {
367373 cast<ValueItem>(this )->~ValueItem ();
368374 break ;
369375 case Kind::ParentTaskMarker:
370- cast<ParentTaskMarkerItem>(this )->~ParentTaskMarkerItem ();
371-
372376 // we're done here; as we must not proceed into the parent owned values.
373377 // we do have to destroy the item pointing at the parent/edge itself though.
374378 stop = true ;
379+ LLVM_FALLTHROUGH;
380+ case Kind::StopLookupMarker:
381+ cast<MarkerItem>(this )->~MarkerItem ();
375382 break ;
376383 }
377384
@@ -442,6 +449,21 @@ bool TaskLocal::Storage::popValue(AsyncTask *task) {
442449 return head != nullptr ;
443450}
444451
452+ void TaskLocal::Storage::pushStopLookup (AsyncTask *task) {
453+ head = MarkerItem::createStopLookupMarker (task, head);
454+ SWIFT_TASK_LOCAL_DEBUG_LOG (nullptr , " push stop node item:%p" , head);
455+ }
456+
457+ void TaskLocal::Storage::popStopLookup (AsyncTask *task) {
458+ assert (head && " attempted to pop stop node off empty task-local stack" );
459+ assert (head->getKind () == Item::Kind::StopLookupMarker &&
460+ " attempted to pop wrong node type" );
461+ auto old = head;
462+ SWIFT_TASK_LOCAL_DEBUG_LOG (nullptr , " pop stop node item:%p" , old);
463+ head = head->getNext ();
464+ old->destroy (task);
465+ }
466+
445467OpaqueValue* TaskLocal::Storage::getValue (AsyncTask *task,
446468 const HeapObject *key) {
447469 assert (key && " TaskLocal key must not be null." );
@@ -452,6 +474,8 @@ OpaqueValue* TaskLocal::Storage::getValue(AsyncTask *task,
452474 if (valueItem->key == key) {
453475 return valueItem->getStoragePtr ();
454476 }
477+ } else if (item->getKind () == Item::Kind::StopLookupMarker) {
478+ break ;
455479 }
456480
457481 item = item->getNext ();
@@ -487,10 +511,30 @@ void TaskLocal::Storage::copyTo(AsyncTask *target) {
487511 " skip copy, already copied most recent value, value was [%p]" ,
488512 valueItem->getStoragePtr ());
489513 }
514+ } else if (item->getKind () == Item::Kind::StopLookupMarker) {
515+ break ;
490516 }
491517 item = item->getNext ();
492518 }
493519}
494520
521+ TaskLocal::StopLookupScope::StopLookupScope () {
522+ task = swift_task_getCurrent ();
523+ storage = Storage::getCurrent (task);
524+ if (storage && storage->isEmpty ()) {
525+ storage = nullptr ;
526+ }
527+
528+ if (storage) {
529+ storage->pushStopLookup (task);
530+ }
531+ }
532+
533+ TaskLocal::StopLookupScope::~StopLookupScope () {
534+ if (storage) {
535+ storage->popStopLookup (task);
536+ }
537+ }
538+
495539#define OVERRIDE_TASK_LOCAL COMPATIBILITY_OVERRIDE
496540#include " ../CompatibilityOverride/CompatibilityOverrideIncludePath.h"
0 commit comments