Skip to content

Commit 658f0ea

Browse files
authored
[Runtime] Refactor layout string runtime functions to simplify future specialization work (#66105)
rdar://109787818 Templatized and abstracted handling of layout strings to simplify future specializations. E.g. specilizing for a particular number of reference count operations can be done by passing the expected size as a template param: ``` extern "C" void swift_generic_destroy_2(swift::OpaqueValue *address, const Metadata *metadata) { handleRefCounts<2, DestroyHandler>(metadata, (uint8_t *)address); } ```
1 parent 9b3faad commit 658f0ea

File tree

1 file changed

+113
-96
lines changed

1 file changed

+113
-96
lines changed

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 113 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -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
4343
template <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
5353
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) {
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

6363
typedef 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

223251
struct 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+
269319
extern "C" swift::OpaqueValue *
270320
swift_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

313330
extern "C" swift::OpaqueValue *

0 commit comments

Comments
 (0)