|
26 | 26 | #include "llvm/Support/SwapByteOrder.h"
|
27 | 27 | #include <cstdint>
|
28 | 28 | #include <limits>
|
| 29 | +#include <type_traits> |
29 | 30 | #if SWIFT_OBJC_INTEROP
|
30 | 31 | #include "swift/Runtime/ObjCBridge.h"
|
31 | 32 | #include <Block.h>
|
@@ -60,24 +61,33 @@ static Metadata *getExistentialTypeMetadata(OpaqueValue *object) {
|
60 | 61 | return reinterpret_cast<Metadata**>(object)[NumWords_ValueBuffer];
|
61 | 62 | }
|
62 | 63 |
|
63 |
| -typedef Metadata* (*MetadataAccessor)(const Metadata* const *); |
| 64 | +template <typename FnTy> |
| 65 | +static const FnTy readRelativeFunctionPointer(const uint8_t *layoutStr, |
| 66 | + size_t &offset) { |
| 67 | + static_assert(std::is_pointer<FnTy>::value); |
64 | 68 |
|
65 |
| -static const Metadata *getResilientTypeMetadata(const Metadata* metadata, |
66 |
| - const uint8_t *layoutStr, |
67 |
| - size_t &offset) { |
68 | 69 | auto absolute = layoutStr + offset;
|
69 | 70 | auto relativeOffset =
|
70 | 71 | (uintptr_t)(intptr_t)(int32_t)readBytes<intptr_t>(layoutStr, offset);
|
71 |
| - MetadataAccessor fn; |
| 72 | + FnTy fn; |
72 | 73 |
|
73 | 74 | #if SWIFT_PTRAUTH
|
74 |
| - fn = (MetadataAccessor)ptrauth_sign_unauthenticated( |
| 75 | + fn = (FnTy)ptrauth_sign_unauthenticated( |
75 | 76 | (void *)((uintptr_t)absolute + relativeOffset),
|
76 | 77 | ptrauth_key_function_pointer, 0);
|
77 | 78 | #else
|
78 |
| - fn = (MetadataAccessor)((uintptr_t)absolute + relativeOffset); |
| 79 | + fn = (FnTy)((uintptr_t)absolute + relativeOffset); |
79 | 80 | #endif
|
80 | 81 |
|
| 82 | + return fn; |
| 83 | +} |
| 84 | + |
| 85 | +typedef Metadata *(*MetadataAccessor)(const Metadata *const *); |
| 86 | + |
| 87 | +static const Metadata *getResilientTypeMetadata(const Metadata *metadata, |
| 88 | + const uint8_t *layoutStr, |
| 89 | + size_t &offset) { |
| 90 | + auto fn = readRelativeFunctionPointer<MetadataAccessor>(layoutStr, offset); |
81 | 91 | return fn(metadata->getGenericArgs());
|
82 | 92 | }
|
83 | 93 |
|
@@ -117,6 +127,13 @@ inline static bool handleNextRefCount(const Metadata *metadata, const uint8_t *t
|
117 | 127 | } else if (SWIFT_UNLIKELY(tag ==
|
118 | 128 | RefCountingKind::SinglePayloadEnumSimple)) {
|
119 | 129 | Handler::handleSinglePayloadEnumSimple(typeLayout, offset, addrOffset, std::forward<Params>(params)...);
|
| 130 | + } else if (SWIFT_UNLIKELY(tag == RefCountingKind::SinglePayloadEnumFN)) { |
| 131 | + Handler::handleSinglePayloadEnumFN(typeLayout, offset, false, addrOffset, |
| 132 | + std::forward<Params>(params)...); |
| 133 | + } else if (SWIFT_UNLIKELY(tag == |
| 134 | + RefCountingKind::SinglePayloadEnumFNResolved)) { |
| 135 | + Handler::handleSinglePayloadEnumFN(typeLayout, offset, true, addrOffset, |
| 136 | + std::forward<Params>(params)...); |
120 | 137 | } else {
|
121 | 138 | Handler::handleReference(tag, addrOffset, std::forward<Params>(params)...);
|
122 | 139 | }
|
@@ -154,8 +171,9 @@ static uint64_t readTagBytes(uint8_t *addr, uint8_t byteCount) {
|
154 | 171 | }
|
155 | 172 | }
|
156 | 173 |
|
157 |
| -static void handleSinglePayloadEnumSimple(const uint8_t *typeLayout, size_t &offset, |
158 |
| - uint8_t *addr, size_t &addrOffset) { |
| 174 | +static void handleSinglePayloadEnumSimple(const uint8_t *typeLayout, |
| 175 | + size_t &offset, uint8_t *addr, |
| 176 | + size_t &addrOffset) { |
159 | 177 | auto byteCountsAndOffset = readBytes<uint64_t>(typeLayout, offset);
|
160 | 178 | auto extraTagBytesPattern = (uint8_t)(byteCountsAndOffset >> 62);
|
161 | 179 | auto xiTagBytesPattern = ((uint8_t)(byteCountsAndOffset >> 59)) & 0x7;
|
@@ -198,6 +216,30 @@ static void handleSinglePayloadEnumSimple(const uint8_t *typeLayout, size_t &off
|
198 | 216 | addrOffset += skip;
|
199 | 217 | }
|
200 | 218 |
|
| 219 | +typedef unsigned (*GetEnumTagFn)(const uint8_t *); |
| 220 | + |
| 221 | +static void handleSinglePayloadEnumFN(const uint8_t *typeLayout, size_t &offset, |
| 222 | + bool resolved, uint8_t *addr, |
| 223 | + size_t &addrOffset) { |
| 224 | + GetEnumTagFn getEnumTag; |
| 225 | + if (resolved) { |
| 226 | + getEnumTag = readBytes<GetEnumTagFn>(typeLayout, offset); |
| 227 | + } else { |
| 228 | + getEnumTag = readRelativeFunctionPointer<GetEnumTagFn>(typeLayout, offset); |
| 229 | + } |
| 230 | + |
| 231 | + unsigned enumTag = getEnumTag(addr + addrOffset); |
| 232 | + |
| 233 | + if (enumTag == 0) { |
| 234 | + offset += sizeof(size_t) * 2; |
| 235 | + } else { |
| 236 | + auto refCountBytes = readBytes<size_t>(typeLayout, offset); |
| 237 | + auto skip = readBytes<size_t>(typeLayout, offset); |
| 238 | + offset += refCountBytes; |
| 239 | + addrOffset += skip; |
| 240 | + } |
| 241 | +} |
| 242 | + |
201 | 243 | const DestroyFuncAndMask destroyTable[] = {
|
202 | 244 | {(DestrFn)&skipDestroy, false},
|
203 | 245 | {(DestrFn)&swift_errorRelease, true},
|
@@ -232,6 +274,13 @@ struct DestroyHandler {
|
232 | 274 | ::handleSinglePayloadEnumSimple(typeLayout, offset, addr, addrOffset);
|
233 | 275 | }
|
234 | 276 |
|
| 277 | + static inline void handleSinglePayloadEnumFN(const uint8_t *typeLayout, |
| 278 | + size_t &offset, bool resolved, |
| 279 | + size_t &addrOffset, |
| 280 | + uint8_t *addr) { |
| 281 | + ::handleSinglePayloadEnumFN(typeLayout, offset, resolved, addr, addrOffset); |
| 282 | + } |
| 283 | + |
235 | 284 | static inline void handleReference(RefCountingKind tag, uintptr_t addrOffset, uint8_t *addr) {
|
236 | 285 | const auto &destroyFunc = destroyTable[static_cast<uint8_t>(tag)];
|
237 | 286 | if (SWIFT_LIKELY(destroyFunc.isIndirect)) {
|
@@ -305,6 +354,14 @@ struct CopyHandler {
|
305 | 354 | ::handleSinglePayloadEnumSimple(typeLayout, offset, (uint8_t *)src, addrOffset);
|
306 | 355 | }
|
307 | 356 |
|
| 357 | + static inline void handleSinglePayloadEnumFN(const uint8_t *typeLayout, |
| 358 | + size_t &offset, bool resolved, |
| 359 | + size_t &addrOffset, |
| 360 | + uint8_t *dest, uint8_t *src) { |
| 361 | + ::handleSinglePayloadEnumFN(typeLayout, offset, resolved, (uint8_t *)src, |
| 362 | + addrOffset); |
| 363 | + } |
| 364 | + |
308 | 365 | static inline void handleReference(RefCountingKind tag, uintptr_t addrOffset, uint8_t *dest, uint8_t *src) {
|
309 | 366 | const auto &retainFunc = retainTable[static_cast<uint8_t>(tag)];
|
310 | 367 | if (SWIFT_LIKELY(retainFunc.isSingle)) {
|
@@ -388,6 +445,18 @@ swift_generic_initWithTake(swift::OpaqueValue *dest, swift::OpaqueValue *src,
|
388 | 445 | break;
|
389 | 446 | }
|
390 | 447 |
|
| 448 | + case RefCountingKind::SinglePayloadEnumFN: { |
| 449 | + handleSinglePayloadEnumFN(typeLayout, offset, false, (uint8_t *)src, |
| 450 | + addrOffset); |
| 451 | + break; |
| 452 | + } |
| 453 | + |
| 454 | + case RefCountingKind::SinglePayloadEnumFNResolved: { |
| 455 | + handleSinglePayloadEnumFN(typeLayout, offset, true, (uint8_t *)src, |
| 456 | + addrOffset); |
| 457 | + break; |
| 458 | + } |
| 459 | + |
391 | 460 | case RefCountingKind::End:
|
392 | 461 | return dest;
|
393 | 462 | default:
|
@@ -439,6 +508,25 @@ void swift::swift_resolve_resilientAccessors(
|
439 | 508 | case RefCountingKind::SinglePayloadEnumSimple:
|
440 | 509 | i += (3 * sizeof(uint64_t)) + (4 * sizeof(size_t));
|
441 | 510 | break;
|
| 511 | + |
| 512 | + case RefCountingKind::SinglePayloadEnumFN: { |
| 513 | + auto getEnumTag = |
| 514 | + readRelativeFunctionPointer<GetEnumTagFn>(fieldLayoutStr, i); |
| 515 | + size_t writeOffset = |
| 516 | + layoutStrOffset + currentOffset - layoutStringHeaderSize; |
| 517 | + uint64_t tagAndOffset = |
| 518 | + (((uint64_t)RefCountingKind::SinglePayloadEnumFNResolved) << 56) | |
| 519 | + size; |
| 520 | + writeBytes(layoutStr, writeOffset, tagAndOffset); |
| 521 | + writeBytes(layoutStr, writeOffset, getEnumTag); |
| 522 | + i += 2 * sizeof(size_t); |
| 523 | + break; |
| 524 | + } |
| 525 | + |
| 526 | + case RefCountingKind::SinglePayloadEnumFNResolved: |
| 527 | + i += 3 * sizeof(size_t); |
| 528 | + break; |
| 529 | + |
442 | 530 | default:
|
443 | 531 | break;
|
444 | 532 | }
|
|
0 commit comments