diff --git a/stdlib/public/runtime/BytecodeLayouts.cpp b/stdlib/public/runtime/BytecodeLayouts.cpp index 278b19bf6dc1a..9f72acd42f93c 100644 --- a/stdlib/public/runtime/BytecodeLayouts.cpp +++ b/stdlib/public/runtime/BytecodeLayouts.cpp @@ -384,43 +384,38 @@ swift_generic_initWithCopy(swift::OpaqueValue *dest, swift::OpaqueValue *src, return dest; } -extern "C" swift::OpaqueValue * -swift_generic_initWithTake(swift::OpaqueValue *dest, swift::OpaqueValue *src, - const Metadata *metadata) { - const uint8_t *typeLayout = metadata->getLayoutString(); - size_t size = metadata->vw_size(); - - memcpy(dest, src, size); - - if (SWIFT_LIKELY(metadata->getValueWitnesses()->isBitwiseTakable())) { - return dest; +struct TakeHandler { + static inline void handleMetatype(const Metadata *type, uintptr_t addrOffset, + uint8_t *dest, uint8_t *src) { + if (SWIFT_UNLIKELY(!type->getValueWitnesses()->isBitwiseTakable())) { + type->vw_initializeWithTake( + (OpaqueValue*)((uintptr_t)dest + addrOffset), + (OpaqueValue*)((uintptr_t)src + addrOffset)); + } } - auto offset = layoutStringHeaderSize; - uintptr_t addrOffset = 0; + static inline void handleSinglePayloadEnumSimple(const uint8_t *typeLayout, + size_t &offset, + uintptr_t &addrOffset, + uint8_t *dest, + uint8_t *src) { + ::handleSinglePayloadEnumSimple(typeLayout, offset, src, addrOffset); + } - while (true) { - uint64_t skip = readBytes(typeLayout, offset); - auto tag = static_cast(skip >> 56); - skip &= ~(0xffULL << 56); - addrOffset += skip; + static inline void handleSinglePayloadEnumFN(const uint8_t *typeLayout, + size_t &offset, bool resolved, + uintptr_t &addrOffset, + uint8_t *dest, uint8_t *src) { + ::handleSinglePayloadEnumFN(typeLayout, offset, resolved, src, addrOffset); + } - switch (tag) { - case RefCountingKind::UnknownWeak: + static inline void handleReference(RefCountingKind tag, uintptr_t addrOffset, + uint8_t *dest, uint8_t *src) { + if (tag == RefCountingKind::UnknownWeak) { swift_unknownObjectWeakTakeInit( - (WeakReference*)((uintptr_t)dest + addrOffset), - (WeakReference*)((uintptr_t)src + addrOffset)); - break; - case RefCountingKind::Metatype: { - auto *type = readBytes(typeLayout, offset); - if (SWIFT_UNLIKELY(!type->getValueWitnesses()->isBitwiseTakable())) { - type->vw_initializeWithTake( - (OpaqueValue*)((uintptr_t)dest + addrOffset), - (OpaqueValue*)((uintptr_t)src + addrOffset)); - } - break; - } - case RefCountingKind::Existential: { + (WeakReference*)((uintptr_t)dest + addrOffset), + (WeakReference*)((uintptr_t)src + addrOffset)); + } else if (tag == RefCountingKind::Existential) { auto *type = getExistentialTypeMetadata( (OpaqueValue*)((uintptr_t)src + addrOffset)); if (SWIFT_UNLIKELY(!type->getValueWitnesses()->isBitwiseTakable())) { @@ -428,42 +423,23 @@ swift_generic_initWithTake(swift::OpaqueValue *dest, swift::OpaqueValue *src, (OpaqueValue*)((uintptr_t)dest + addrOffset), (OpaqueValue*)((uintptr_t)src + addrOffset)); } - break; - } - case RefCountingKind::Resilient: { - auto *type = getResilientTypeMetadata(metadata, typeLayout, offset); - if (SWIFT_UNLIKELY(!type->getValueWitnesses()->isBitwiseTakable())) { - type->vw_initializeWithTake((OpaqueValue*)((uintptr_t)dest + addrOffset), - (OpaqueValue*)((uintptr_t)src + addrOffset)); - } - break; - } - - case RefCountingKind::SinglePayloadEnumSimple: { - handleSinglePayloadEnumSimple(typeLayout, offset, (uint8_t *)src, - addrOffset); - break; } + } +}; - case RefCountingKind::SinglePayloadEnumFN: { - handleSinglePayloadEnumFN(typeLayout, offset, false, (uint8_t *)src, - addrOffset); - break; - } +extern "C" swift::OpaqueValue * +swift_generic_initWithTake(swift::OpaqueValue *dest, swift::OpaqueValue *src, + const Metadata *metadata) { + size_t size = metadata->vw_size(); - case RefCountingKind::SinglePayloadEnumFNResolved: { - handleSinglePayloadEnumFN(typeLayout, offset, true, (uint8_t *)src, - addrOffset); - break; - } + memcpy(dest, src, size); - case RefCountingKind::End: - return dest; - default: - break; - } + if (SWIFT_LIKELY(metadata->getValueWitnesses()->isBitwiseTakable())) { + return dest; } + handleRefCounts<0, TakeHandler>(metadata, (uint8_t *)dest, (uint8_t *)src); + return dest; }