@@ -41,7 +41,7 @@ static const size_t layoutStringHeaderSize = sizeof(uint64_t) + sizeof(size_t);
41
41
// / Given a pointer and an offset, read the requested data and increment the
42
42
// / offset
43
43
template <typename T>
44
- T readBytes (const uint8_t *typeLayout, size_t &i) {
44
+ static T readBytes (const uint8_t *typeLayout, size_t &i) {
45
45
T returnVal;
46
46
memcpy (&returnVal, typeLayout + i, sizeof (T));
47
47
i += sizeof (T);
@@ -51,18 +51,18 @@ T readBytes(const uint8_t *typeLayout, size_t &i) {
51
51
// / Given a pointer, a value, and an offset, write the value at the given
52
52
// / offset and increment offset by the size of T
53
53
template <typename T>
54
- void writeBytes (uint8_t *typeLayout, size_t &i, T value) {
54
+ static void writeBytes (uint8_t *typeLayout, size_t &i, T value) {
55
55
memcpy (typeLayout + i, &value, sizeof (T));
56
56
i += sizeof (T);
57
57
}
58
58
59
- Metadata *getExistentialTypeMetadata (OpaqueValue *object) {
59
+ static Metadata *getExistentialTypeMetadata (OpaqueValue *object) {
60
60
return reinterpret_cast <Metadata**>(object)[NumWords_ValueBuffer];
61
61
}
62
62
63
63
typedef Metadata* (*MetadataAccessor)(const Metadata* const *);
64
64
65
- const Metadata *getResilientTypeMetadata (const Metadata* metadata,
65
+ static const Metadata *getResilientTypeMetadata (const Metadata* metadata,
66
66
const uint8_t *layoutStr,
67
67
size_t &offset) {
68
68
auto absolute = layoutStr + offset;
@@ -88,9 +88,9 @@ struct DestroyFuncAndMask {
88
88
bool isIndirect;
89
89
};
90
90
91
- void skipDestroy (void * ignore) { }
91
+ static void skipDestroy (void * ignore) { }
92
92
93
- void existential_destroy (OpaqueValue* object) {
93
+ static void existential_destroy (OpaqueValue* object) {
94
94
auto * metadata = getExistentialTypeMetadata (object);
95
95
if (metadata->getValueWitnesses ()->isValueInline ()) {
96
96
metadata->vw_destroy (object);
@@ -99,31 +99,47 @@ void existential_destroy(OpaqueValue* object) {
99
99
}
100
100
}
101
101
102
- const DestroyFuncAndMask destroyTable[] = {
103
- {(DestrFn)&skipDestroy, false },
104
- {(DestrFn)&swift_errorRelease, true },
105
- {(DestrFn)&swift_release, true },
106
- {(DestrFn)&swift_unownedRelease, true },
107
- {(DestrFn)&swift_weakDestroy, false },
108
- {(DestrFn)&swift_unknownObjectRelease, true },
109
- {(DestrFn)&swift_unknownObjectUnownedDestroy, false },
110
- {(DestrFn)&swift_unknownObjectWeakDestroy, false },
111
- {(DestrFn)&swift_bridgeObjectRelease, true },
112
- #if SWIFT_OBJC_INTEROP
113
- {(DestrFn)&_Block_release, true },
114
- {(DestrFn)&swift_unknownObjectRelease, true },
115
- #else
116
- {nullptr , true },
117
- {nullptr , true },
118
- #endif
119
- // TODO: how to handle Custom?
120
- {nullptr , true },
121
- {nullptr , true },
122
- {nullptr , true },
123
- {(DestrFn)&existential_destroy, false },
124
- };
102
+ template <typename Handler, typename ... Params>
103
+ inline static bool handleNextRefCount (const Metadata *metadata, const uint8_t *typeLayout, size_t &offset, uintptr_t &addrOffset, Params... params) {
104
+ uint64_t skip = readBytes<uint64_t >(typeLayout, offset);
105
+ auto tag = static_cast <RefCountingKind>(skip >> 56 );
106
+ skip &= ~(0xffULL << 56 );
107
+ addrOffset += skip;
108
+
109
+ if (SWIFT_UNLIKELY (tag == RefCountingKind::End)) {
110
+ return false ;
111
+ } else if (SWIFT_UNLIKELY (tag == RefCountingKind::Metatype)) {
112
+ auto *type = readBytes<const Metadata*>(typeLayout, offset);
113
+ Handler::handleMetatype (type, addrOffset, std::forward<Params>(params)...);
114
+ } else if (SWIFT_UNLIKELY (tag == RefCountingKind::Resilient)) {
115
+ auto *type = getResilientTypeMetadata (metadata, typeLayout, offset);
116
+ Handler::handleMetatype (type, addrOffset, std::forward<Params>(params)...);
117
+ } else if (SWIFT_UNLIKELY (tag ==
118
+ RefCountingKind::SinglePayloadEnumSimple)) {
119
+ Handler::handleSinglePayloadEnumSimple (typeLayout, offset, addrOffset, std::forward<Params>(params)...);
120
+ } else {
121
+ Handler::handleReference (tag, addrOffset, std::forward<Params>(params)...);
122
+ }
123
+
124
+ return true ;
125
+ }
126
+
127
+ template <unsigned N, typename Handler, typename ... Params>
128
+ inline static void handleRefCounts (const Metadata *metadata, Params... params) {
129
+ const uint8_t *typeLayout = metadata->getLayoutString ();
130
+ size_t offset = layoutStringHeaderSize;
131
+ uintptr_t addrOffset = 0 ;
132
+
133
+ if (N == 0 ) {
134
+ while (handleNextRefCount<Handler>(metadata, typeLayout, offset, addrOffset, std::forward<Params>(params)...)) {}
135
+ } else {
136
+ for (int i = 0 ; i < N; i++) {
137
+ handleNextRefCount<Handler>(metadata, typeLayout, offset, addrOffset, std::forward<Params>(params)...);
138
+ }
139
+ }
140
+ }
125
141
126
- uint64_t readTagBytes (uint8_t *addr, uint8_t byteCount) {
142
+ static uint64_t readTagBytes (uint8_t *addr, uint8_t byteCount) {
127
143
switch (byteCount) {
128
144
case 1 :
129
145
return addr[0 ];
@@ -138,7 +154,7 @@ uint64_t readTagBytes(uint8_t *addr, uint8_t byteCount) {
138
154
}
139
155
}
140
156
141
- void handleSinglePayloadEnumSimple (const uint8_t *typeLayout, size_t &offset,
157
+ static void handleSinglePayloadEnumSimple (const uint8_t *typeLayout, size_t &offset,
142
158
uint8_t *addr, size_t &addrOffset) {
143
159
auto byteCountsAndOffset = readBytes<uint64_t >(typeLayout, offset);
144
160
auto extraTagBytesPattern = (uint8_t )(byteCountsAndOffset >> 62 );
@@ -182,42 +198,54 @@ void handleSinglePayloadEnumSimple(const uint8_t *typeLayout, size_t &offset,
182
198
addrOffset += skip;
183
199
}
184
200
185
- extern " C" void
186
- swift_generic_destroy (swift::OpaqueValue *address, const Metadata *metadata) {
187
- uint8_t *addr = (uint8_t *)address;
188
-
189
- const uint8_t *typeLayout = metadata->getLayoutString ();
201
+ const DestroyFuncAndMask destroyTable[] = {
202
+ {(DestrFn)&skipDestroy, false },
203
+ {(DestrFn)&swift_errorRelease, true },
204
+ {(DestrFn)&swift_release, true },
205
+ {(DestrFn)&swift_unownedRelease, true },
206
+ {(DestrFn)&swift_weakDestroy, false },
207
+ {(DestrFn)&swift_unknownObjectRelease, true },
208
+ {(DestrFn)&swift_unknownObjectUnownedDestroy, false },
209
+ {(DestrFn)&swift_unknownObjectWeakDestroy, false },
210
+ {(DestrFn)&swift_bridgeObjectRelease, true },
211
+ #if SWIFT_OBJC_INTEROP
212
+ {(DestrFn)&_Block_release, true },
213
+ {(DestrFn)&swift_unknownObjectRelease, true },
214
+ #else
215
+ {nullptr , true },
216
+ {nullptr , true },
217
+ #endif
218
+ // TODO: how to handle Custom?
219
+ {nullptr , true },
220
+ {nullptr , true },
221
+ {nullptr , true },
222
+ {(DestrFn)&existential_destroy, false },
223
+ };
190
224
191
- size_t offset = layoutStringHeaderSize;
192
- uintptr_t addrOffset = 0 ;
225
+ struct DestroyHandler {
226
+ static inline void handleMetatype (const Metadata *type, uintptr_t addrOffset, uint8_t *addr) {
227
+ type->vw_destroy ((OpaqueValue *)(addr + addrOffset));
228
+ }
193
229
194
- while (true ) {
195
- uint64_t skip = readBytes<uint64_t >(typeLayout, offset);
196
- auto tag = static_cast <RefCountingKind>(skip >> 56 );
197
- skip &= ~(0xffULL << 56 );
198
- addrOffset += skip;
230
+ static inline void handleSinglePayloadEnumSimple (const uint8_t *typeLayout, size_t &offset,
231
+ size_t &addrOffset, uint8_t *addr) {
232
+ ::handleSinglePayloadEnumSimple (typeLayout, offset, addr, addrOffset);
233
+ }
199
234
200
- if (SWIFT_UNLIKELY (tag == RefCountingKind::End)) {
201
- return ;
202
- } else if (SWIFT_UNLIKELY (tag == RefCountingKind::Metatype)) {
203
- auto *type = readBytes<const Metadata*>(typeLayout, offset);
204
- type->vw_destroy ((OpaqueValue *)(addr + addrOffset));
205
- } else if (SWIFT_UNLIKELY (tag == RefCountingKind::Resilient)) {
206
- auto *type = getResilientTypeMetadata (metadata, typeLayout, offset);
207
- type->vw_destroy ((OpaqueValue *)(addr + addrOffset));
208
- } else if (SWIFT_UNLIKELY (tag ==
209
- RefCountingKind::SinglePayloadEnumSimple)) {
210
- handleSinglePayloadEnumSimple (typeLayout, offset, addr, addrOffset);
235
+ static inline void handleReference (RefCountingKind tag, uintptr_t addrOffset, uint8_t *addr) {
236
+ const auto &destroyFunc = destroyTable[static_cast <uint8_t >(tag)];
237
+ if (SWIFT_LIKELY (destroyFunc.isIndirect )) {
238
+ destroyFunc.fn (
239
+ (void *)((*(uintptr_t *)(addr + addrOffset))));
211
240
} else {
212
- const auto &destroyFunc = destroyTable[static_cast <uint8_t >(tag)];
213
- if (SWIFT_LIKELY (destroyFunc.isIndirect )) {
214
- destroyFunc.fn (
215
- (void *)((*(uintptr_t *)(addr + addrOffset))));
216
- } else {
217
- destroyFunc.fn (((void *)(addr + addrOffset)));
218
- }
241
+ destroyFunc.fn (((void *)(addr + addrOffset)));
219
242
}
220
243
}
244
+ };
245
+
246
+ extern " C" void
247
+ swift_generic_destroy (swift::OpaqueValue *address, const Metadata *metadata) {
248
+ handleRefCounts<0 , DestroyHandler>(metadata, (uint8_t *)address);
221
249
}
222
250
223
251
struct RetainFuncAndMask {
@@ -266,48 +294,37 @@ const RetainFuncAndMask retainTable[] = {
266
294
{(void *)&existential_initializeWithCopy, false },
267
295
};
268
296
297
+ struct CopyHandler {
298
+ static inline void handleMetatype (const Metadata *type, uintptr_t addrOffset, uint8_t *dest, uint8_t *src) {
299
+ type->vw_initializeWithCopy ((OpaqueValue*)((uintptr_t )dest + addrOffset),
300
+ (OpaqueValue*)((uintptr_t )src + addrOffset));
301
+ }
302
+
303
+ static inline void handleSinglePayloadEnumSimple (const uint8_t *typeLayout, size_t &offset,
304
+ size_t &addrOffset, uint8_t *dest, uint8_t *src) {
305
+ ::handleSinglePayloadEnumSimple (typeLayout, offset, (uint8_t *)src, addrOffset);
306
+ }
307
+
308
+ static inline void handleReference (RefCountingKind tag, uintptr_t addrOffset, uint8_t *dest, uint8_t *src) {
309
+ const auto &retainFunc = retainTable[static_cast <uint8_t >(tag)];
310
+ if (SWIFT_LIKELY (retainFunc.isSingle )) {
311
+ ((RetainFn)retainFunc.fn )(*(void **)(((uintptr_t )dest + addrOffset)));
312
+ } else {
313
+ ((CopyInitFn)retainFunc.fn )((void *)((uintptr_t )dest + addrOffset),
314
+ (void *)((uintptr_t )src + addrOffset));
315
+ }
316
+ }
317
+ };
318
+
269
319
extern " C" swift::OpaqueValue *
270
320
swift_generic_initWithCopy (swift::OpaqueValue *dest, swift::OpaqueValue *src,
271
321
const Metadata *metadata) {
272
- uintptr_t addrOffset = 0 ;
273
- const uint8_t *typeLayout = metadata->getLayoutString ();
274
-
275
322
size_t size = metadata->vw_size ();
276
-
277
- auto offset = layoutStringHeaderSize;
278
-
279
323
memcpy (dest, src, size);
280
324
281
- while (true ) {
282
- uint64_t skip = readBytes<uint64_t >(typeLayout, offset);
283
- auto tag = static_cast <RefCountingKind>(skip >> 56 );
284
- skip &= ~(0xffULL << 56 );
285
- addrOffset += skip;
325
+ handleRefCounts<0 , CopyHandler>(metadata, (uint8_t *)dest, (uint8_t *)src);
286
326
287
- if (SWIFT_UNLIKELY (tag == RefCountingKind::End)) {
288
- return dest;
289
- } else if (SWIFT_UNLIKELY (tag == RefCountingKind::Metatype)) {
290
- auto *type = readBytes<const Metadata*>(typeLayout, offset);
291
- type->vw_initializeWithCopy ((OpaqueValue*)((uintptr_t )dest + addrOffset),
292
- (OpaqueValue*)((uintptr_t )src + addrOffset));
293
- } else if (SWIFT_UNLIKELY (tag == RefCountingKind::Resilient)) {
294
- auto *type = getResilientTypeMetadata (metadata, typeLayout, offset);
295
- type->vw_initializeWithCopy ((OpaqueValue*)((uintptr_t )dest + addrOffset),
296
- (OpaqueValue*)((uintptr_t )src + addrOffset));
297
- } else if (SWIFT_UNLIKELY (tag ==
298
- RefCountingKind::SinglePayloadEnumSimple)) {
299
- handleSinglePayloadEnumSimple (typeLayout, offset, (uint8_t *)src,
300
- addrOffset);
301
- } else {
302
- const auto &retainFunc = retainTable[static_cast <uint8_t >(tag)];
303
- if (SWIFT_LIKELY (retainFunc.isSingle )) {
304
- ((RetainFn)retainFunc.fn )(*(void **)(((uintptr_t )dest + addrOffset)));
305
- } else {
306
- ((CopyInitFn)retainFunc.fn )((void *)((uintptr_t )dest + addrOffset),
307
- (void *)((uintptr_t )src + addrOffset));
308
- }
309
- }
310
- }
327
+ return dest;
311
328
}
312
329
313
330
extern " C" swift::OpaqueValue *
0 commit comments