@@ -41,7 +41,7 @@ static const size_t layoutStringHeaderSize = sizeof(uint64_t) + sizeof(size_t);
4141// / Given a pointer and an offset, read the requested data and increment the
4242// / offset
4343template <typename T>
44- T readBytes (const uint8_t *typeLayout, size_t &i) {
44+ static T readBytes (const uint8_t *typeLayout, size_t &i) {
4545 T returnVal;
4646 memcpy (&returnVal, typeLayout + i, sizeof (T));
4747 i += sizeof (T);
@@ -51,18 +51,18 @@ T readBytes(const uint8_t *typeLayout, size_t &i) {
5151// / Given a pointer, a value, and an offset, write the value at the given
5252// / offset and increment offset by the size of T
5353template <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) {
5555 memcpy (typeLayout + i, &value, sizeof (T));
5656 i += sizeof (T);
5757}
5858
59- Metadata *getExistentialTypeMetadata (OpaqueValue *object) {
59+ static Metadata *getExistentialTypeMetadata (OpaqueValue *object) {
6060 return reinterpret_cast <Metadata**>(object)[NumWords_ValueBuffer];
6161}
6262
6363typedef Metadata* (*MetadataAccessor)(const Metadata* const *);
6464
65- const Metadata *getResilientTypeMetadata (const Metadata* metadata,
65+ static const Metadata *getResilientTypeMetadata (const Metadata* metadata,
6666 const uint8_t *layoutStr,
6767 size_t &offset) {
6868 auto absolute = layoutStr + offset;
@@ -88,9 +88,9 @@ struct DestroyFuncAndMask {
8888 bool isIndirect;
8989};
9090
91- void skipDestroy (void * ignore) { }
91+ static void skipDestroy (void * ignore) { }
9292
93- void existential_destroy (OpaqueValue* object) {
93+ static void existential_destroy (OpaqueValue* object) {
9494 auto * metadata = getExistentialTypeMetadata (object);
9595 if (metadata->getValueWitnesses ()->isValueInline ()) {
9696 metadata->vw_destroy (object);
@@ -99,31 +99,47 @@ void existential_destroy(OpaqueValue* object) {
9999 }
100100}
101101
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+ }
125141
126- uint64_t readTagBytes (uint8_t *addr, uint8_t byteCount) {
142+ static uint64_t readTagBytes (uint8_t *addr, uint8_t byteCount) {
127143 switch (byteCount) {
128144 case 1 :
129145 return addr[0 ];
@@ -138,7 +154,7 @@ uint64_t readTagBytes(uint8_t *addr, uint8_t byteCount) {
138154 }
139155}
140156
141- void handleSinglePayloadEnumSimple (const uint8_t *typeLayout, size_t &offset,
157+ static void handleSinglePayloadEnumSimple (const uint8_t *typeLayout, size_t &offset,
142158 uint8_t *addr, size_t &addrOffset) {
143159 auto byteCountsAndOffset = readBytes<uint64_t >(typeLayout, offset);
144160 auto extraTagBytesPattern = (uint8_t )(byteCountsAndOffset >> 62 );
@@ -182,42 +198,54 @@ void handleSinglePayloadEnumSimple(const uint8_t *typeLayout, size_t &offset,
182198 addrOffset += skip;
183199}
184200
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+ };
190224
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+ }
193229
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+ }
199234
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))));
211240 } 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)));
219242 }
220243 }
244+ };
245+
246+ extern " C" void
247+ swift_generic_destroy (swift::OpaqueValue *address, const Metadata *metadata) {
248+ handleRefCounts<0 , DestroyHandler>(metadata, (uint8_t *)address);
221249}
222250
223251struct RetainFuncAndMask {
@@ -266,48 +294,37 @@ const RetainFuncAndMask retainTable[] = {
266294 {(void *)&existential_initializeWithCopy, false },
267295};
268296
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+
269319extern " C" swift::OpaqueValue *
270320swift_generic_initWithCopy (swift::OpaqueValue *dest, swift::OpaqueValue *src,
271321 const Metadata *metadata) {
272- uintptr_t addrOffset = 0 ;
273- const uint8_t *typeLayout = metadata->getLayoutString ();
274-
275322 size_t size = metadata->vw_size ();
276-
277- auto offset = layoutStringHeaderSize;
278-
279323 memcpy (dest, src, size);
280324
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);
286326
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;
311328}
312329
313330extern " C" swift::OpaqueValue *
0 commit comments