From 382b2fc89e664ea8103ba81cb71fb0e7dca54b50 Mon Sep 17 00:00:00 2001 From: Mykola Pokhylets Date: Wed, 1 Oct 2025 17:01:25 +0200 Subject: [PATCH] Fix swift_bridgeObjectRetain() dropping integer bits In particular this was breaking deferred type-checking of arrays. Regression was introduced in https://github.com/swiftlang/swift/commit/724a9a7da404a0635fb9717a3f0f578dbbe0eb28 --- stdlib/public/runtime/SwiftObject.mm | 30 ++++------------------------ 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm index 97d28325ed162..78aa562de0f51 100644 --- a/stdlib/public/runtime/SwiftObject.mm +++ b/stdlib/public/runtime/SwiftObject.mm @@ -677,20 +677,6 @@ static bool isBridgeObjectTaggedPointer(void *object) { return (void*)(uintptr_t(object) & ~unTaggedNonNativeBridgeObjectBits); } -#if SWIFT_OBJC_INTEROP -#if __arm64__ -// Marking this as noinline allows swift_bridgeObjectRetain to avoid emitting -// a stack frame for the swift_retain path on ARM64. It makes for worse codegen -// on x86-64, though, so limit it to ARM64. -SWIFT_NOINLINE -#endif -static void *objcRetainAndReturn(void *object) { - auto const objectRef = toPlainObject_unTagged_bridgeObject(object); - objc_retain(static_cast(objectRef)); - return object; -} -#endif - void *swift::swift_bridgeObjectRetain(void *object) { #if SWIFT_OBJC_INTEROP if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object)) @@ -698,22 +684,14 @@ static bool isBridgeObjectTaggedPointer(void *object) { #endif auto const objectRef = toPlainObject_unTagged_bridgeObject(object); - #if SWIFT_OBJC_INTEROP if (!isNonNative_unTagged_bridgeObject(object)) { - return swift_retain(static_cast(objectRef)); + swift_retain(static_cast(objectRef)); + return object; } - - // Put the call to objc_retain in a separate function, tail-called here. This - // allows the fast path of swift_bridgeObjectRetain to avoid creating a stack - // frame on ARM64. We can't directly tail-call objc_retain, because - // swift_bridgeObjectRetain returns the pointer with objectPointerIsObjCBit - // set, so we have to make a non-tail call and then return the value with the - // bit set. - SWIFT_MUSTTAIL return objcRetainAndReturn(object); + objc_retain(static_cast(objectRef)); + return object; #else - // No tail call here. When !SWIFT_OBJC_INTEROP, the value of objectRef may be - // different from that of object, e.g. on Linux ARM64. swift_retain(static_cast(objectRef)); return object; #endif