Skip to content

Commit b85a2a3

Browse files
committed
[IRGen+Runtime] Fix tag bit mask handling for objc, unknown objects and blocks
rdar://138487964 On platforms that don't have reserved bits in objc (including unknown) pointers, we use the spare bits for Swift enums, so they have to be masked out. Blocks don't have reserved bits on any platform.
1 parent bba4f65 commit b85a2a3

File tree

4 files changed

+159
-17
lines changed

4 files changed

+159
-17
lines changed

lib/IRGen/TypeLayout.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
#include "TypeLayout.h"
13+
#include "ClassTypeInfo.h"
1314
#include "ConstantBuilder.h"
1415
#include "EnumPayload.h"
1516
#include "FixedTypeInfo.h"
@@ -1293,14 +1294,17 @@ bool ScalarTypeLayoutEntry::refCountString(IRGenModule &IGM,
12931294
case ScalarKind::BlockReference:
12941295
B.addRefCount(LayoutStringBuilder::RefCountingKind::Block, size);
12951296
break;
1296-
case ScalarKind::ObjCReference:
1297-
if (typeInfo.hasFixedSpareBits()) {
1297+
case ScalarKind::ObjCReference: {
1298+
auto *classTI = dyn_cast<ClassTypeInfo>(&typeInfo);
1299+
assert(classTI);
1300+
if (!classTI->getClass()->hasClangNode()) {
12981301
B.addRefCount(LayoutStringBuilder::RefCountingKind::NativeSwiftObjC,
12991302
size);
13001303
} else {
13011304
B.addRefCount(LayoutStringBuilder::RefCountingKind::ObjC, size);
13021305
}
13031306
break;
1307+
}
13041308
case ScalarKind::ThickFunc:
13051309
B.addSkip(IGM.getPointerSize().getValue());
13061310
B.addRefCount(LayoutStringBuilder::RefCountingKind::NativeStrong,

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,12 @@ static void weakDestroy(const Metadata *metadata, LayoutStringReader1 &reader,
281281
static void unknownDestroy(const Metadata *metadata,
282282
LayoutStringReader1 &reader, uintptr_t &addrOffset,
283283
uint8_t *addr) {
284-
void *object = *(void**)(addr + addrOffset);
284+
uintptr_t object = *(uintptr_t *)(addr + addrOffset);
285285
addrOffset += sizeof(void*);
286-
swift_unknownObjectRelease(object);
286+
if (_swift_abi_ObjCReservedBitsMask == 0) {
287+
object &= ~_swift_abi_SwiftSpareBitsMask;
288+
}
289+
swift_unknownObjectRelease((void *)object);
287290
}
288291

289292
static void unknownUnownedDestroy(const Metadata *metadata,
@@ -769,9 +772,10 @@ multiPayloadEnumGeneric(const Metadata *metadata, LayoutStringReader1 &reader,
769772
static void blockDestroy(const Metadata *metadata, LayoutStringReader1 &reader,
770773
uintptr_t &addrOffset, uint8_t *addr) {
771774
#if SWIFT_OBJC_INTEROP
772-
void* object = (void *)(addr + addrOffset);
775+
uintptr_t object = *(uintptr_t *)(addr + addrOffset);
776+
object &= ~_swift_abi_SwiftSpareBitsMask;
773777
addrOffset += sizeof(void*);
774-
_Block_release(object);
778+
_Block_release((void *)object);
775779
#else
776780
swift_unreachable("Blocks are not available on this platform");
777781
#endif
@@ -783,6 +787,11 @@ static void objcStrongDestroy(const Metadata *metadata,
783787
#if SWIFT_OBJC_INTEROP
784788
uintptr_t object = *(uintptr_t *)(addr + addrOffset);
785789
addrOffset += sizeof(objc_object*);
790+
791+
if (_swift_abi_ObjCReservedBitsMask == 0) {
792+
object &= ~_swift_abi_SwiftSpareBitsMask;
793+
}
794+
786795
objc_release((objc_object *)object);
787796
#else
788797
swift_unreachable("ObjC interop is not available on this platform");
@@ -959,10 +968,13 @@ static void weakCopyInit(const Metadata *metadata, LayoutStringReader1 &reader,
959968
static void unknownRetain(const Metadata *metadata, LayoutStringReader1 &reader,
960969
uintptr_t &addrOffset, uint8_t *dest, uint8_t *src) {
961970
uintptr_t _addrOffset = addrOffset;
962-
void *object = *(void **)(src + _addrOffset);
971+
uintptr_t object = *(uintptr_t *)(src + _addrOffset);
963972
memcpy(dest + _addrOffset, &object, sizeof(void*));
964973
addrOffset = _addrOffset + sizeof(void *);
965-
swift_unknownObjectRetain(object);
974+
if (_swift_abi_ObjCReservedBitsMask == 0) {
975+
object &= ~_swift_abi_SwiftSpareBitsMask;
976+
}
977+
swift_unknownObjectRetain((void *)object);
966978
}
967979

968980
static void unknownUnownedCopyInit(const Metadata *metadata,
@@ -1000,9 +1012,11 @@ static void blockCopy(const Metadata *metadata, LayoutStringReader1 &reader,
10001012
uintptr_t &addrOffset, uint8_t *dest, uint8_t *src) {
10011013
#if SWIFT_OBJC_INTEROP
10021014
uintptr_t _addrOffset = addrOffset;
1003-
auto *copy = _Block_copy(*(void**)(src + _addrOffset));
1004-
memcpy(dest + _addrOffset, &copy, sizeof(void*));
1015+
uintptr_t object = *(uintptr_t *)(src + _addrOffset);
1016+
memcpy(dest + _addrOffset, &object, sizeof(void *));
10051017
addrOffset = _addrOffset + sizeof(void*);
1018+
object &= ~_swift_abi_SwiftSpareBitsMask;
1019+
_Block_copy((void *)object);
10061020
#else
10071021
swift_unreachable("Blocks are not available on this platform");
10081022
#endif
@@ -1016,6 +1030,11 @@ static void objcStrongRetain(const Metadata *metadata,
10161030
uintptr_t object = *(uintptr_t *)(src + _addrOffset);
10171031
memcpy(dest + _addrOffset, &object, sizeof(objc_object *));
10181032
addrOffset = _addrOffset + sizeof(objc_object *);
1033+
1034+
if (_swift_abi_ObjCReservedBitsMask == 0) {
1035+
object &= ~_swift_abi_SwiftSpareBitsMask;
1036+
}
1037+
10191038
objc_retain((objc_object *)object);
10201039
#else
10211040
swift_unreachable("ObjC interop is not available on this platform");
@@ -1368,12 +1387,16 @@ static void unknownAssignWithCopy(const Metadata *metadata,
13681387
uintptr_t &addrOffset, uint8_t *dest,
13691388
uint8_t *src) {
13701389
uintptr_t _addrOffset = addrOffset;
1371-
void *destObject = *(void **)(dest + _addrOffset);
1372-
void *srcObject = *(void **)(src + _addrOffset);
1390+
uintptr_t destObject = *(uintptr_t *)(dest + _addrOffset);
1391+
uintptr_t srcObject = *(uintptr_t *)(src + _addrOffset);
13731392
memcpy(dest + _addrOffset, &srcObject, sizeof(void *));
13741393
addrOffset = _addrOffset + sizeof(void *);
1375-
swift_unknownObjectRelease(destObject);
1376-
swift_unknownObjectRetain(srcObject);
1394+
if (_swift_abi_ObjCReservedBitsMask == 0) {
1395+
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1396+
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
1397+
}
1398+
swift_unknownObjectRelease((void *)destObject);
1399+
swift_unknownObjectRetain((void *)srcObject);
13771400
}
13781401

13791402
static void bridgeAssignWithCopy(const Metadata *metadata,
@@ -1431,10 +1454,14 @@ static void blockAssignWithCopy(const Metadata *metadata,
14311454
uint8_t *src) {
14321455
#if SWIFT_OBJC_INTEROP
14331456
uintptr_t _addrOffset = addrOffset;
1434-
_Block_release(*(void **)(dest + _addrOffset));
1435-
auto *copy = _Block_copy(*(void **)(src + _addrOffset));
1436-
memcpy(dest + _addrOffset, &copy, sizeof(void*));
1457+
uintptr_t destObject = *(uintptr_t *)(dest + _addrOffset);
1458+
uintptr_t srcObject = *(uintptr_t *)(src + _addrOffset);
1459+
memcpy(dest + _addrOffset, &srcObject, sizeof(void *));
14371460
addrOffset = _addrOffset + sizeof(void*);
1461+
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1462+
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
1463+
_Block_release((void *)destObject);
1464+
_Block_copy((void *)srcObject);
14381465
#else
14391466
swift_unreachable("Blocks are not available on this platform");
14401467
#endif
@@ -1452,6 +1479,11 @@ static void objcStrongAssignWithCopy(const Metadata *metadata,
14521479
memcpy(dest + _addrOffset, &srcObject, sizeof(objc_object*));
14531480
addrOffset = _addrOffset + sizeof(objc_object*);
14541481

1482+
if (_swift_abi_ObjCReservedBitsMask == 0) {
1483+
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1484+
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
1485+
}
1486+
14551487
objc_release((objc_object *)destObject);
14561488
objc_retain((objc_object *)srcObject);
14571489
#else

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,23 @@ public enum ErrorWrapper {
667667
case y(Error)
668668
}
669669

670+
public enum MultiPayloadAnyObject {
671+
case x(AnyObject)
672+
case y(AnyObject)
673+
case z(AnyObject)
674+
}
675+
676+
public enum MultiPayloadBlock {
677+
#if _pointerBitWidth(_32)
678+
public typealias PaddingPayload = (Int16, Int8, Bool)
679+
#else
680+
public typealias PaddingPayload = (Int32, Int16, Int8, Bool)
681+
#endif
682+
683+
case x(PaddingPayload)
684+
case y(@convention(block) () -> Void)
685+
}
686+
670687
@inline(never)
671688
public func consume<T>(_ x: T.Type) {
672689
withExtendedLifetime(x) {}

test/Interpreter/layout_string_witnesses_static.swift

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,95 @@ func testMultiPayloadOneExtraTagValue() {
13631363

13641364
testMultiPayloadOneExtraTagValue()
13651365

1366+
func testMultiPayloadAnyObject() {
1367+
let ptr = UnsafeMutablePointer<MultiPayloadAnyObject>.allocate(capacity: 1)
1368+
1369+
// initWithCopy
1370+
do {
1371+
let x = MultiPayloadAnyObject.y(SimpleClass(x: 0))
1372+
testInit(ptr, to: x)
1373+
}
1374+
1375+
// assignWithTake
1376+
do {
1377+
let y = MultiPayloadAnyObject.z(SimpleClass(x: 1))
1378+
1379+
// CHECK-NEXT: Before deinit
1380+
print("Before deinit")
1381+
1382+
// CHECK-NEXT: SimpleClass deinitialized!
1383+
testAssign(ptr, from: y)
1384+
}
1385+
1386+
// assignWithCopy
1387+
do {
1388+
var z = MultiPayloadAnyObject.z(SimpleClass(x: 2))
1389+
1390+
// CHECK-NEXT: Before deinit
1391+
print("Before deinit")
1392+
1393+
// CHECK-NEXT: SimpleClass deinitialized!
1394+
testAssignCopy(ptr, from: &z)
1395+
}
1396+
1397+
// CHECK-NEXT: Before deinit
1398+
print("Before deinit")
1399+
1400+
// destroy
1401+
// CHECK-NEXT: SimpleClass deinitialized!
1402+
testDestroy(ptr)
1403+
1404+
ptr.deallocate()
1405+
}
1406+
1407+
testMultiPayloadAnyObject()
1408+
1409+
func testMultiPayloadBlock() {
1410+
let ptr = UnsafeMutablePointer<MultiPayloadBlock>.allocate(capacity: 1)
1411+
1412+
// initWithCopy
1413+
do {
1414+
let instance = SimpleClass(x: 0)
1415+
let x = MultiPayloadBlock.y({ print(instance) })
1416+
testInit(ptr, to: x)
1417+
}
1418+
1419+
// assignWithTake
1420+
do {
1421+
let instance = SimpleClass(x: 1)
1422+
let y = MultiPayloadBlock.y({ print(instance) })
1423+
1424+
// CHECK-NEXT: Before deinit
1425+
print("Before deinit")
1426+
1427+
// CHECK-NEXT: SimpleClass deinitialized!
1428+
testAssign(ptr, from: y)
1429+
}
1430+
1431+
// assignWithCopy
1432+
do {
1433+
let instance = SimpleClass(x: 2)
1434+
var z = MultiPayloadBlock.y({ print(instance) })
1435+
1436+
// CHECK-NEXT: Before deinit
1437+
print("Before deinit")
1438+
1439+
// CHECK-NEXT: SimpleClass deinitialized!
1440+
testAssignCopy(ptr, from: &z)
1441+
}
1442+
1443+
// CHECK-NEXT: Before deinit
1444+
print("Before deinit")
1445+
1446+
// destroy
1447+
// CHECK-NEXT: SimpleClass deinitialized!
1448+
testDestroy(ptr)
1449+
1450+
ptr.deallocate()
1451+
}
1452+
1453+
testMultiPayloadBlock()
1454+
13661455
#if os(macOS)
13671456
func testObjc() {
13681457
let ptr = UnsafeMutablePointer<ObjcWrapper>.allocate(capacity: 1)

0 commit comments

Comments
 (0)