@@ -28,27 +28,27 @@ struct SwiftError;
28
28
class TaskStatusRecord ;
29
29
class TaskGroup ;
30
30
31
+ extern FullMetadata<HeapMetadata> taskLocalHeapItemHeapMetadata;
32
+
31
33
// ==== Task Locals Values ---------------------------------------------------
32
34
33
35
class TaskLocal {
34
36
public:
35
37
// / Type of the pointed at `next` task local item.
36
38
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 ,
42
39
// / The storage pointer points at the next TaskLocal::Item in this task.
43
- IsNext = 0b01 ,
40
+ IsNext = 0b00 ,
44
41
// / The storage pointer points at a item stored by another AsyncTask.
45
42
// /
46
43
// / Note that this may not necessarily be the same as the task's parent
47
44
// / task -- we may point to a super-parent if we know / that the parent
48
45
// / does not "contribute" any task local values. This is to speed up
49
46
// / lookups by skipping empty parent tasks during get(), and explained
50
47
// / 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
52
52
};
53
53
54
54
// / Values must match `TaskLocalInheritance` declared in `TaskLocal.swift`.
@@ -70,37 +70,41 @@ class TaskLocal {
70
70
// / - specifically from the current task itself
71
71
// /
72
72
// / Such values are *not* accessible from child tasks or detached tasks.
73
- Never = 1
73
+ Never = 1
74
74
};
75
75
76
76
class Item {
77
77
private:
78
78
// / Mask used for the low status bits in a task local chain item.
79
79
static const uintptr_t statusMask = 0x03 ;
80
80
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.
84
88
uintptr_t next;
85
89
86
90
public:
87
91
// / The type of the key with which this value is associated.
88
- const Metadata *keyType ;
92
+ const HeapObject *key ;
89
93
// / The type of the value stored by this item.
90
94
const Metadata *valueType;
91
95
92
96
// Trailing storage for the value itself. The storage will be
93
97
// uninitialized or contain an instance of \c valueType.
94
98
95
- private :
99
+ protected :
96
100
explicit Item ()
97
101
: next(0 ),
98
- keyType (nullptr ),
102
+ key (nullptr ),
99
103
valueType(nullptr ) {}
100
104
101
- explicit Item (const Metadata *keyType , const Metadata *valueType)
105
+ explicit Item (const HeapObject *key , const Metadata *valueType)
102
106
: next(0 ),
103
- keyType(keyType ),
107
+ key(key ),
104
108
valueType(valueType) {}
105
109
106
110
public:
@@ -116,7 +120,7 @@ class TaskLocal {
116
120
static Item *createParentLink (AsyncTask *task, AsyncTask *parent);
117
121
118
122
static Item *createLink (AsyncTask *task,
119
- const Metadata *keyType ,
123
+ const HeapObject *key ,
120
124
const Metadata *valueType);
121
125
122
126
void destroy (AsyncTask *task);
@@ -125,25 +129,32 @@ class TaskLocal {
125
129
return reinterpret_cast <Item *>(next & ~statusMask);
126
130
}
127
131
128
- NextLinkType getNextLinkType () {
132
+ NextLinkType getNextLinkType () const {
129
133
return static_cast <NextLinkType>(next & statusMask);
130
134
}
131
135
136
+ bool isHeapItem () const {
137
+ return getNextLinkType () == NextLinkType::ThisItemIsHeapItem;
138
+ }
139
+
132
140
// / Item does not contain any actual value, and is only used to point at
133
141
// / a specific parent item.
134
- bool isEmpty () {
142
+ bool isEmpty () const {
135
143
return !valueType;
136
144
}
137
145
138
146
// / Retrieve a pointer to the storage of the value.
139
147
OpaqueValue *getStoragePtr () {
148
+ fprintf (stderr, " [%s:%d] (%s) GET STORAGE\n " , __FILE__, __LINE__, __FUNCTION__);
140
149
return reinterpret_cast <OpaqueValue *>(
141
- reinterpret_cast <char *>(this ) + storageOffset (valueType));
150
+ reinterpret_cast <char *>(this ) + storageOffset (isHeapItem (), valueType));
142
151
}
143
152
144
153
// / 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) {
146
155
size_t offset = sizeof (Item);
156
+
157
+
147
158
if (valueType) {
148
159
size_t alignment = valueType->vw_alignment ();
149
160
return (offset + alignment - 1 ) & ~(alignment - 1 );
@@ -153,15 +164,53 @@ class TaskLocal {
153
164
}
154
165
155
166
// / 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;
158
171
if (valueType) {
159
172
offset += valueType->vw_size ();
160
173
}
161
174
return offset;
162
175
}
163
176
};
164
177
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
+ };
165
214
166
215
class Storage {
167
216
friend class TaskLocal ::Item;
@@ -202,11 +251,11 @@ class TaskLocal {
202
251
void initializeLinkParent (AsyncTask *task, AsyncTask *parent);
203
252
204
253
void pushValue (AsyncTask *task,
205
- const Metadata *keyType ,
254
+ const HeapObject *key ,
206
255
/* +1 */ OpaqueValue *value, const Metadata *valueType);
207
256
208
257
OpaqueValue* getValue (AsyncTask *task,
209
- const Metadata *keyType ,
258
+ const HeapObject *key ,
210
259
TaskLocalInheritance inheritance);
211
260
212
261
void popValue (AsyncTask *task);
0 commit comments