Skip to content

Commit bfeea09

Browse files
authored
Merge pull request #67869 from mikeash/class-copy-fixup-heap-destroyer-5.9
[5.9][Runtime] Fix up the heap destroyer in objc_setClassCopyFixupHandler.
2 parents 0027fac + 2cb8fac commit bfeea09

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

include/swift/ABI/Metadata.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ struct HeapObject;
8181
class WeakReference;
8282
struct UnownedReference;
8383

84+
using HeapObjectDestroyer =
85+
SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *);
86+
8487
/// The result of requesting type metadata. Generally the return value of
8588
/// a function.
8689
///
@@ -514,9 +517,6 @@ struct TargetOpaqueMetadata {
514517
TargetMetadata<Runtime> base;
515518
};
516519

517-
using HeapObjectDestroyer =
518-
SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *);
519-
520520
/// The prefix on a heap metadata.
521521
template <typename Runtime>
522522
struct TargetHeapMetadataHeaderPrefix {
@@ -561,6 +561,14 @@ struct TargetHeapMetadata : TargetMetadata<Runtime> {
561561
: TargetMetadata<Runtime>(kind) {}
562562
constexpr TargetHeapMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa)
563563
: TargetMetadata<Runtime>(isa) {}
564+
565+
HeapObjectDestroyer *getHeapObjectDestroyer() const {
566+
return asFullMetadata(this)->destroy;
567+
}
568+
569+
void setHeapObjectDestroyer(HeapObjectDestroyer *destroy) {
570+
asFullMetadata(this)->destroy = destroy;
571+
}
564572
};
565573
using HeapMetadata = TargetHeapMetadata<InProcess>;
566574

stdlib/public/runtime/Metadata.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,11 @@ static void swift_objc_classCopyFixupHandler(Class oldClass, Class newClass) {
499499
if (!oldClassMetadata->isTypeMetadata())
500500
return;
501501

502-
// Copy the value witness table pointer for pointer authentication.
502+
// Copy the value witness table and pointer and heap object destroyer for
503+
// pointer authentication.
503504
auto newClassMetadata = reinterpret_cast<ClassMetadata *>(newClass);
504505
newClassMetadata->setValueWitnesses(oldClassMetadata->getValueWitnesses());
506+
newClassMetadata->setHeapObjectDestroyer(oldClassMetadata->getHeapObjectDestroyer());
505507

506508
// Otherwise, re-sign v-table entries using the extra discriminators stored
507509
// in the v-table descriptor.

test/Interpreter/SDK/dynamic_subclass.swift

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,37 @@
66
import Foundation
77
import ObjectiveC
88

9-
func DoSwizzle(_ c: AnyClass) -> AnyClass {
9+
func DoSwizzle<T: AnyObject>(_ c: T.Type) -> T.Type {
1010
let name = String(utf8String: class_getName(c))!
1111
let subclass: AnyClass = objc_allocateClassPair(c, "\(name)Subclass", 0)!
1212
objc_registerClassPair(subclass);
1313
let subclassSubclass: AnyClass = objc_allocateClassPair(subclass, "\(name)SubclassSubclass", 0)!
1414
objc_registerClassPair(subclassSubclass);
15-
return subclassSubclass
16-
}
17-
18-
class MySwiftClassToBeSwizzled: NSObject {
15+
return subclassSubclass as! T.Type
1916
}
2017

2118
_ = DoSwizzle(NSArray.self)
2219
print("Swizzled NSArray")
2320
// CHECK: Swizzled NSArray
2421

25-
_ = DoSwizzle(MySwiftClassToBeSwizzled.self)
22+
// Ensure that we can dynamically subclass, instantiate, and destroy Swift
23+
// classes, both NSObject-inheriting and native Swift.
24+
class MySwiftClassToBeSwizzled {
25+
required init() {}
26+
}
27+
28+
let swiftSubclass = DoSwizzle(MySwiftClassToBeSwizzled.self)
2629
print("Swizzled MySwiftClassToBeSwizzled")
2730
// CHECK: Swizzled MySwiftClassToBeSwizzled
31+
print("Instantiated the subclass: \(swiftSubclass.init())")
32+
// CHECK: Instantiated the subclass:
33+
34+
class MyNSObjectSwiftClassToBeSwizzled: NSObject {
35+
required override init() {}
36+
}
37+
38+
let swiftNSObjectSubclass = DoSwizzle(MyNSObjectSwiftClassToBeSwizzled.self)
39+
print("Swizzled MyNSObjectSwiftClassToBeSwizzled")
40+
// CHECK: Swizzled MyNSObjectSwiftClassToBeSwizzled
41+
print("Instantiated the subclass: \(swiftNSObjectSubclass.init())")
42+
// CHECK: Instantiated the subclass:

0 commit comments

Comments
 (0)