@@ -28,27 +28,27 @@ struct SwiftError;
2828class TaskStatusRecord ;
2929class TaskGroup ;
3030
31+ extern FullMetadata<HeapMetadata> taskLocalHeapItemHeapMetadata;
32+
3133// ==== Task Locals Values ---------------------------------------------------
3234
3335class TaskLocal {
3436public:
3537 // / Type of the pointed at `next` task local item.
3638 enum class NextLinkType : uintptr_t {
37- // / This task is known to be a "terminal" node in the lookup of task locals.
38- // / In other words, even if it had a parent, the parent (and its parents)
39- // / are known to not contain any any more task locals, and thus any further
40- // / search beyond this task.
41- IsTerminal = 0b00 ,
4239 // / The storage pointer points at the next TaskLocal::Item in this task.
43- IsNext = 0b01 ,
40+ IsNext = 0b00 ,
4441 // / The storage pointer points at a item stored by another AsyncTask.
4542 // /
4643 // / Note that this may not necessarily be the same as the task's parent
4744 // / task -- we may point to a super-parent if we know / that the parent
4845 // / does not "contribute" any task local values. This is to speed up
4946 // / lookups by skipping empty parent tasks during get(), and explained
5047 // / in depth in `createParentLink`.
51- IsParent = 0b11
48+ IsParent = 0b01 ,
49+
50+ // / The next item is "unstructured" and must be ref-counted.
51+ ThisItemIsHeapItem = 0b10
5252 };
5353
5454 // / Values must match `TaskLocalInheritance` declared in `TaskLocal.swift`.
@@ -70,37 +70,41 @@ class TaskLocal {
7070 // / - specifically from the current task itself
7171 // /
7272 // / Such values are *not* accessible from child tasks or detached tasks.
73- Never = 1
73+ Never = 1
7474 };
7575
7676 class Item {
7777 private:
7878 // / Mask used for the low status bits in a task local chain item.
7979 static const uintptr_t statusMask = 0x03 ;
8080
81- // / Pointer to the next task local item; be it in this task or in a parent.
82- // / Low bits encode `NextLinkType`.
83- // / Item *next = nullptr;
81+ // / Pointer to one of the following:
82+ // / - next task local item as OpaqueValue* if it is task-local allocated
83+ // / - next task local item as HeapObject* if it is heap allocated "heavy"
84+ // / - the parent task's TaskLocal::Storage
85+ // /
86+ // / Low bits encode `NextLinkType`, based on which the type of the pointer
87+ // / is determined.
8488 uintptr_t next;
8589
8690 public:
8791 // / The type of the key with which this value is associated.
88- const Metadata *keyType ;
92+ const HeapObject *key ;
8993 // / The type of the value stored by this item.
9094 const Metadata *valueType;
9195
9296 // Trailing storage for the value itself. The storage will be
9397 // uninitialized or contain an instance of \c valueType.
9498
95- private :
99+ protected :
96100 explicit Item ()
97101 : next(0 ),
98- keyType (nullptr ),
102+ key (nullptr ),
99103 valueType(nullptr ) {}
100104
101- explicit Item (const Metadata *keyType , const Metadata *valueType)
105+ explicit Item (const HeapObject *key , const Metadata *valueType)
102106 : next(0 ),
103- keyType(keyType ),
107+ key(key ),
104108 valueType(valueType) {}
105109
106110 public:
@@ -116,7 +120,7 @@ class TaskLocal {
116120 static Item *createParentLink (AsyncTask *task, AsyncTask *parent);
117121
118122 static Item *createLink (AsyncTask *task,
119- const Metadata *keyType ,
123+ const HeapObject *key ,
120124 const Metadata *valueType);
121125
122126 void destroy (AsyncTask *task);
@@ -125,25 +129,32 @@ class TaskLocal {
125129 return reinterpret_cast <Item *>(next & ~statusMask);
126130 }
127131
128- NextLinkType getNextLinkType () {
132+ NextLinkType getNextLinkType () const {
129133 return static_cast <NextLinkType>(next & statusMask);
130134 }
131135
136+ bool isHeapItem () const {
137+ return getNextLinkType () == NextLinkType::ThisItemIsHeapItem;
138+ }
139+
132140 // / Item does not contain any actual value, and is only used to point at
133141 // / a specific parent item.
134- bool isEmpty () {
142+ bool isEmpty () const {
135143 return !valueType;
136144 }
137145
138146 // / Retrieve a pointer to the storage of the value.
139147 OpaqueValue *getStoragePtr () {
148+ fprintf (stderr, " [%s:%d] (%s) GET STORAGE\n " , __FILE__, __LINE__, __FUNCTION__);
140149 return reinterpret_cast <OpaqueValue *>(
141- reinterpret_cast <char *>(this ) + storageOffset (valueType));
150+ reinterpret_cast <char *>(this ) + storageOffset (isHeapItem (), valueType));
142151 }
143152
144153 // / Compute the offset of the storage from the base of the item.
145- static size_t storageOffset (const Metadata *valueType) {
154+ static size_t storageOffset (bool isHeapItem, const Metadata *valueType) {
146155 size_t offset = sizeof (Item);
156+
157+
147158 if (valueType) {
148159 size_t alignment = valueType->vw_alignment ();
149160 return (offset + alignment - 1 ) & ~(alignment - 1 );
@@ -153,15 +164,53 @@ class TaskLocal {
153164 }
154165
155166 // / Determine the size of the item given a particular value type.
156- static size_t itemSize (const Metadata *valueType) {
157- size_t offset = storageOffset (valueType);
167+ static size_t itemSize (bool isHeapItem, const Metadata *valueType) {
168+ size_t offset = storageOffset (isHeapItem, valueType);
169+ size_t headerSize = isHeapItem ? sizeof (HeapObject) : 0 ;
170+ offset += headerSize;
158171 if (valueType) {
159172 offset += valueType->vw_size ();
160173 }
161174 return offset;
162175 }
163176 };
164177
178+ // / Heap allocated version of TaskLocal::Item.
179+ // / It is used in limited un-structured concurrency cases, where the task
180+ // / local must be stored on the heap for the time being.
181+ // /
182+ // / MUST HAVE THE SAME LAYOUT AS TaskLocal::Item.
183+ // / FIXME: how to actually make this work...
184+ // / get the address of "after heap object" and cast that to Item?
185+ class HeapItem : public HeapObject , public Item {
186+ public:
187+
188+ explicit HeapItem (const HeapMetadata *metadata = &taskLocalHeapItemHeapMetadata)
189+ : HeapObject(metadata),
190+ Item() {}
191+
192+ explicit HeapItem (const HeapObject *key, const Metadata *valueType)
193+ : HeapItem(&taskLocalHeapItemHeapMetadata, key, valueType) {}
194+
195+ explicit HeapItem (const HeapMetadata *metadata,
196+ const HeapObject *key, const Metadata *valueType)
197+ : HeapObject(metadata),
198+ Item(key, valueType) {}
199+
200+
201+ // / Retrieve a pointer to the `Item` that is part of this object.
202+ TaskLocal::Item *getItem () {
203+ fprintf (stderr, " [%s:%d] (%s) GET ITEM PTR, heapItem:%p\n " , __FILE__, __LINE__, __FUNCTION__, this );
204+ return reinterpret_cast <TaskLocal::Item *>(
205+ reinterpret_cast <char *>(this ) + itemOffset ());
206+ }
207+
208+ // / Compute the offset of `Item` part of this object.
209+ static size_t itemOffset () {
210+ size_t offset = sizeof (HeapObject);
211+ return offset;
212+ }
213+ };
165214
166215 class Storage {
167216 friend class TaskLocal ::Item;
@@ -202,11 +251,11 @@ class TaskLocal {
202251 void initializeLinkParent (AsyncTask *task, AsyncTask *parent);
203252
204253 void pushValue (AsyncTask *task,
205- const Metadata *keyType ,
254+ const HeapObject *key ,
206255 /* +1 */ OpaqueValue *value, const Metadata *valueType);
207256
208257 OpaqueValue* getValue (AsyncTask *task,
209- const Metadata *keyType ,
258+ const HeapObject *key ,
210259 TaskLocalInheritance inheritance);
211260
212261 void popValue (AsyncTask *task);
0 commit comments