Skip to content

Commit edd9955

Browse files
committed
[Runtime] Fix SwiftError handling in CVW runtime
rdar://138085348 Even though errors are ObjC boxes, they can't be tagged pointers and in fact may use that bit to store enum tags, so treating them like regular ObjC references here can cause ref count issues.
1 parent 95e0a79 commit edd9955

File tree

3 files changed

+24
-13
lines changed

3 files changed

+24
-13
lines changed

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,6 @@ static void handleEnd(const Metadata *metadata,
249249
static void errorDestroy(const Metadata *metadata, LayoutStringReader1 &reader,
250250
uintptr_t &addrOffset, uint8_t *addr) {
251251
uintptr_t object = *(uintptr_t *)(addr + addrOffset);
252-
if (object & _swift_abi_ObjCReservedBitsMask)
253-
return;
254252
object &= ~_swift_abi_SwiftSpareBitsMask;
255253
addrOffset += sizeof(SwiftError*);
256254
swift_errorRelease((SwiftError *)object);
@@ -911,8 +909,6 @@ static void errorRetain(const Metadata *metadata, LayoutStringReader1 &reader,
911909
uintptr_t &addrOffset, uint8_t *dest, uint8_t *src) {
912910
uintptr_t _addrOffset = addrOffset;
913911
uintptr_t object = *(uintptr_t *)(src + _addrOffset);
914-
if (object & _swift_abi_ObjCReservedBitsMask)
915-
return;
916912
memcpy(dest + addrOffset, &object, sizeof(SwiftError*));
917913
object &= ~_swift_abi_SwiftSpareBitsMask;
918914
addrOffset = _addrOffset + sizeof(SwiftError *);
@@ -1306,15 +1302,10 @@ static void errorAssignWithCopy(const Metadata *metadata,
13061302
memcpy(dest + _addrOffset, &srcObject, sizeof(SwiftError *));
13071303
addrOffset = _addrOffset + sizeof(SwiftError *);
13081304

1309-
if (!(destObject & _swift_abi_ObjCReservedBitsMask)) {
1310-
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1311-
swift_errorRelease((SwiftError *)destObject);
1312-
}
1313-
1314-
if (!(srcObject & _swift_abi_ObjCReservedBitsMask)) {
1315-
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
1316-
swift_errorRetain((SwiftError *)srcObject);
1317-
}
1305+
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1306+
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
1307+
swift_errorRelease((SwiftError *)destObject);
1308+
swift_errorRetain((SwiftError *)srcObject);
13181309
}
13191310

13201311
static void nativeStrongAssignWithCopy(const Metadata *metadata,

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ public enum MultiPayloadError {
617617
case empty
618618
case error1(Int, Error)
619619
case error2(Int, Error)
620+
case error3(Int, Error)
620621
}
621622

622623
public enum TwoPayloadInner {
@@ -661,6 +662,11 @@ public enum OneExtraTagValue {
661662
case z
662663
}
663664

665+
public enum ErrorWrapper {
666+
case x(Error)
667+
case y(Error)
668+
}
669+
664670
@inline(never)
665671
public func consume<T>(_ x: T.Type) {
666672
withExtendedLifetime(x) {}

test/Interpreter/layout_string_witnesses_static.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,19 @@ func testMultiPayloadError() {
11751175
// CHECK-NEXT: SimpleClass deinitialized!
11761176
testDestroy(ptr)
11771177

1178+
// initWithCopy
1179+
do {
1180+
let x = MultiPayloadError.error3(0, MyError(x: SimpleClass(x: 23)))
1181+
testInit(ptr, to: x)
1182+
}
1183+
1184+
// CHECK-NEXT: Before deinit
1185+
print("Before deinit")
1186+
1187+
// destroy
1188+
// CHECK-NEXT: SimpleClass deinitialized!
1189+
testDestroy(ptr)
1190+
11781191
ptr.deallocate()
11791192
}
11801193

@@ -1194,6 +1207,7 @@ func testMultiPayloadErrorKeepsTagIntact() {
11941207
switch ptr.pointee {
11951208
case .error1: print("Get error1!")
11961209
case .error2: print("Got error2!")
1210+
case .error3: print("Got error3!")
11971211
case .empty: print("Got empty!")
11981212
}
11991213

0 commit comments

Comments
 (0)