Skip to content

Commit 4726543

Browse files
authored
Merge pull request #77383 from drexin/wip-139106139
[IRGen+Runtime] Differentiate between pure Swift and regular ObjC ref…
2 parents 305ac20 + 4e7ce5a commit 4726543

File tree

4 files changed

+112
-29
lines changed

4 files changed

+112
-29
lines changed

lib/IRGen/TypeLayout.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class LayoutStringBuilder {
7070
Bridge = 0x08,
7171
Block = 0x09,
7272
ObjC = 0x0a,
73-
Custom = 0x0b,
73+
NativeSwiftObjC = 0x0b,
7474

7575
// reserved
7676
// Metatype = 0x0c,
@@ -1294,7 +1294,12 @@ bool ScalarTypeLayoutEntry::refCountString(IRGenModule &IGM,
12941294
B.addRefCount(LayoutStringBuilder::RefCountingKind::Block, size);
12951295
break;
12961296
case ScalarKind::ObjCReference:
1297-
B.addRefCount(LayoutStringBuilder::RefCountingKind::ObjC, size);
1297+
if (typeInfo.hasFixedSpareBits()) {
1298+
B.addRefCount(LayoutStringBuilder::RefCountingKind::NativeSwiftObjC,
1299+
size);
1300+
} else {
1301+
B.addRefCount(LayoutStringBuilder::RefCountingKind::ObjC, size);
1302+
}
12981303
break;
12991304
case ScalarKind::ThickFunc:
13001305
B.addSkip(IGM.getPointerSize().getValue());

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,15 @@ static uint64_t readTagBytes(const uint8_t *addr, uint8_t byteCount) {
127127
uint64_t TAG = 0; \
128128
uintptr_t OFFSET = 0; \
129129
\
130-
_Pragma("clang diagnostic push") \
131-
_Pragma("clang diagnostic ignored \"-Wgnu-label-as-value\"") \
132-
const void *dispatchTable[] = { \
133-
&&done, &&Error, &&NativeStrong, &&NativeUnowned, \
134-
&&NativeWeak, &&Unknown, &&UnknownUnowned, &&UnknownWeak, \
135-
&&Bridge, &&Block, &&ObjC, &&Custom, \
136-
&&Metatype, &&Generic, &&Existential, &&Resilient, \
137-
&&Default, &&Default, &&Default, &&Default, \
138-
&&Default, &&Default, &&Default, \
130+
_Pragma("clang diagnostic push") _Pragma( \
131+
"clang diagnostic ignored \"-Wgnu-label-as-value\"") \
132+
const void *dispatchTable[] = { \
133+
&&done, &&Error, &&NativeStrong, &&NativeUnowned, \
134+
&&NativeWeak, &&Unknown, &&UnknownUnowned, &&UnknownWeak, \
135+
&&Bridge, &&Block, &&ObjC, &&NativeSwiftObjC, \
136+
&&Metatype, &&Generic, &&Existential, &&Resilient, \
137+
&&Default, &&Default, &&Default, &&Default, \
138+
&&Default, &&Default, &&Default, \
139139
}; \
140140
\
141141
[[clang::nomerge]] { \
@@ -194,8 +194,9 @@ static uint64_t readTagBytes(const uint8_t *addr, uint8_t byteCount) {
194194
CONTINUE(METADATA, READER, ADDR_OFFSET, __VA_ARGS__); \
195195
} \
196196
[[clang::nomerge]] { \
197-
Custom: \
198-
swift_unreachable(""); \
197+
NativeSwiftObjC: \
198+
FN_TABLE[11](METADATA, READER, ADDR_OFFSET, __VA_ARGS__); \
199+
CONTINUE(METADATA, READER, ADDR_OFFSET, __VA_ARGS__); \
199200
} \
200201
[[clang::nomerge]] { \
201202
Metatype: \
@@ -782,9 +783,18 @@ static void objcStrongDestroy(const Metadata *metadata,
782783
#if SWIFT_OBJC_INTEROP
783784
uintptr_t object = *(uintptr_t *)(addr + addrOffset);
784785
addrOffset += sizeof(objc_object*);
785-
if (object & _swift_abi_ObjCReservedBitsMask)
786-
return;
786+
objc_release((objc_object *)object);
787+
#else
788+
swift_unreachable("ObjC interop is not available on this platform");
789+
#endif
790+
}
787791

792+
static void nativeSwiftObjcStrongDestroy(const Metadata *metadata,
793+
LayoutStringReader1 &reader,
794+
uintptr_t &addrOffset, uint8_t *addr) {
795+
#if SWIFT_OBJC_INTEROP
796+
uintptr_t object = *(uintptr_t *)(addr + addrOffset);
797+
addrOffset += sizeof(objc_object *);
788798
object &= ~_swift_abi_SwiftSpareBitsMask;
789799
objc_release((objc_object *)object);
790800
#else
@@ -838,7 +848,7 @@ constexpr DestrFn destroyTable[] = {
838848
&bridgeDestroy,
839849
&blockDestroy,
840850
&objcStrongDestroy,
841-
nullptr, // Custom
851+
&nativeSwiftObjcStrongDestroy,
842852
&metatypeDestroy,
843853
nullptr, // Generic
844854
&existentialDestroy,
@@ -1006,8 +1016,21 @@ static void objcStrongRetain(const Metadata *metadata,
10061016
uintptr_t object = *(uintptr_t *)(src + _addrOffset);
10071017
memcpy(dest + _addrOffset, &object, sizeof(objc_object *));
10081018
addrOffset = _addrOffset + sizeof(objc_object *);
1009-
if (object & _swift_abi_ObjCReservedBitsMask)
1010-
return;
1019+
objc_retain((objc_object *)object);
1020+
#else
1021+
swift_unreachable("ObjC interop is not available on this platform");
1022+
#endif
1023+
}
1024+
1025+
static void nativeSwiftObjcStrongRetain(const Metadata *metadata,
1026+
LayoutStringReader1 &reader,
1027+
uintptr_t &addrOffset, uint8_t *dest,
1028+
uint8_t *src) {
1029+
#if SWIFT_OBJC_INTEROP
1030+
uintptr_t _addrOffset = addrOffset;
1031+
uintptr_t object = *(uintptr_t *)(src + _addrOffset);
1032+
memcpy(dest + _addrOffset, &object, sizeof(objc_object *));
1033+
addrOffset = _addrOffset + sizeof(objc_object *);
10111034
object &= ~_swift_abi_SwiftSpareBitsMask;
10121035
objc_retain((objc_object *)object);
10131036
#else
@@ -1069,7 +1092,7 @@ constexpr InitFn initWithCopyTable[] = {
10691092
&bridgeRetain,
10701093
&blockCopy,
10711094
&objcStrongRetain,
1072-
nullptr, // Custom
1095+
&nativeSwiftObjcStrongRetain,
10731096
&metatypeInitWithCopy,
10741097
nullptr, // Generic
10751098
&existentialInitWithCopy,
@@ -1429,15 +1452,29 @@ static void objcStrongAssignWithCopy(const Metadata *metadata,
14291452
memcpy(dest + _addrOffset, &srcObject, sizeof(objc_object*));
14301453
addrOffset = _addrOffset + sizeof(objc_object*);
14311454

1432-
if (!(destObject & _swift_abi_ObjCReservedBitsMask)) {
1433-
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1434-
objc_release((objc_object *)destObject);
1435-
}
1455+
objc_release((objc_object *)destObject);
1456+
objc_retain((objc_object *)srcObject);
1457+
#else
1458+
swift_unreachable("ObjC interop is not available on this platform");
1459+
#endif
1460+
}
14361461

1437-
if (!(srcObject & _swift_abi_ObjCReservedBitsMask)) {
1438-
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
1439-
objc_retain((objc_object *)srcObject);
1440-
}
1462+
static void nativeSwiftObjcStrongAssignWithCopy(const Metadata *metadata,
1463+
LayoutStringReader1 &reader,
1464+
uintptr_t &addrOffset,
1465+
uint8_t *dest, uint8_t *src) {
1466+
#if SWIFT_OBJC_INTEROP
1467+
uintptr_t _addrOffset = addrOffset;
1468+
uintptr_t destObject = *(uintptr_t *)(dest + _addrOffset);
1469+
uintptr_t srcObject = *(uintptr_t *)(src + _addrOffset);
1470+
memcpy(dest + _addrOffset, &srcObject, sizeof(objc_object *));
1471+
addrOffset = _addrOffset + sizeof(objc_object *);
1472+
1473+
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1474+
objc_release((objc_object *)destObject);
1475+
1476+
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
1477+
objc_retain((objc_object *)srcObject);
14411478
#else
14421479
swift_unreachable("ObjC interop is not available on this platform");
14431480
#endif
@@ -1873,7 +1910,7 @@ constexpr InitFn assignWithCopyTable[] = {
18731910
&bridgeAssignWithCopy,
18741911
&blockAssignWithCopy,
18751912
&objcStrongAssignWithCopy,
1876-
nullptr, // Custom
1913+
&nativeSwiftObjcStrongAssignWithCopy,
18771914
&metatypeAssignWithCopy,
18781915
nullptr, // Generic
18791916
&existentialAssignWithCopy,

stdlib/public/runtime/BytecodeLayouts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ enum class RefCountingKind : uint8_t {
3636
Bridge = 0x08,
3737
Block = 0x09,
3838
ObjC = 0x0a,
39-
Custom = 0x0b,
39+
NativeSwiftObjC = 0x0b,
4040

4141
Metatype = 0x0c,
4242
Generic = 0x0d,

test/Interpreter/layout_string_witnesses_objc.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,44 @@ func testMultiPayloadObjCExistentialWrapper() {
9292
}
9393

9494
testMultiPayloadObjCExistentialWrapper()
95+
96+
@objc
97+
class SwiftObjC: NSObject {
98+
deinit {
99+
print("SwiftObjC deinitialized!")
100+
}
101+
}
102+
103+
enum MultiPayloadNativeSwiftObjC {
104+
case x(SwiftObjC)
105+
case y(SwiftObjC)
106+
case z(SwiftObjC)
107+
}
108+
109+
func testMultiPayloadNativeSwiftObjC() {
110+
let ptr = allocateInternalGenericPtr(of: MultiPayloadNativeSwiftObjC.self)
111+
112+
do {
113+
let x = MultiPayloadNativeSwiftObjC.y(SwiftObjC())
114+
testGenericInit(ptr, to: x)
115+
}
116+
117+
do {
118+
let y = MultiPayloadNativeSwiftObjC.z(SwiftObjC())
119+
// CHECK: Before deinit
120+
print("Before deinit")
121+
122+
// CHECK-NEXT: SwiftObjC deinitialized!
123+
testGenericAssign(ptr, from: y)
124+
}
125+
126+
// CHECK-NEXT: Before deinit
127+
print("Before deinit")
128+
129+
// CHECK-NEXT: SwiftObjC deinitialized!
130+
testGenericDestroy(ptr, of: MultiPayloadNativeSwiftObjC.self)
131+
132+
ptr.deallocate()
133+
}
134+
135+
testMultiPayloadNativeSwiftObjC()

0 commit comments

Comments
 (0)