mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When ObjC interop is enabled, we emit what we think will be the class's InstanceStart and InstanceSize based on what we know about the superclass. We then fix up those values at runtime if they don't match. The compiler will emit this data into read-only memory if it knows they will always match, and then the runtime avoids writing to these fields if they already contain the correct value.
However, the compiler aligns the InstanceStart, but instance size is not aligned. For example:
class Super<T> { var bool = true }
class Sub: Super<Int> { var obj: AnyObject? }
Super's InstanceSize is 17 (on 64-bit) but Sub's InstanceStart is 24. The compiler sees a fixed layout and emits Sub's rodata into constant memory. The runtime sees that 24 does not equal 17 and tries to update it, but we don't want it to.
Instead, only update InstanceStart if it's too small to accommodate the superclass's InstanceSize. If it's overlay large then we'll just leave it alone. The compiler underestimates InstanceStart when it doesn't know the superclass's size so this should only happen due to alignment.
rdar://123695998
62 lines
1.6 KiB
Swift
62 lines
1.6 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift %s -o %t/subclass_instance_start_adjustment
|
|
// RUN: %target-codesign %t/subclass_instance_start_adjustment
|
|
// RUN: %target-run %t/subclass_instance_start_adjustment | %FileCheck %s
|
|
|
|
// REQUIRES: executable_test
|
|
// UNSUPPORTED: use_os_stdlib
|
|
// UNSUPPORTED: back_deployment_runtime
|
|
|
|
// Make sure we get the InstanceStart adjustment right for concrete subclasses
|
|
// of generic classes with different sizes, and especially with an unaligned
|
|
// size.
|
|
|
|
class GenericSuperclassWithAlignedSize<T> {
|
|
var field = 42
|
|
}
|
|
|
|
class SubclassOfGenericSuperclassWithAlignedSize: GenericSuperclassWithAlignedSize<Int> {
|
|
var subfield = 43
|
|
}
|
|
|
|
do {
|
|
let obj = SubclassOfGenericSuperclassWithAlignedSize()
|
|
print(obj, obj.field, obj.subfield)
|
|
// CHECK: SubclassOfGenericSuperclassWithAlignedSize 42 43
|
|
}
|
|
|
|
class GenericSuperclassWithMisalignedSize<T> {
|
|
var field = true
|
|
}
|
|
|
|
class SubclassOfGenericSuperclassWithMisalignedSize: GenericSuperclassWithMisalignedSize<Int> {
|
|
var subfield = 44
|
|
}
|
|
|
|
do {
|
|
let obj = SubclassOfGenericSuperclassWithMisalignedSize()
|
|
print(obj, obj.field, obj.subfield)
|
|
// CHECK: SubclassOfGenericSuperclassWithMisalignedSize true 44
|
|
}
|
|
|
|
#if canImport(Foundation)
|
|
import Foundation
|
|
|
|
class GenericSuperclassWithURLField<T> {
|
|
var field: URL?
|
|
}
|
|
|
|
class SubclassOfGenericSuperclassWithURLField: GenericSuperclassWithURLField<Int> {
|
|
var subfield = 45
|
|
}
|
|
|
|
do {
|
|
let obj = SubclassOfGenericSuperclassWithURLField()
|
|
print(obj, obj.field as Any, obj.subfield)
|
|
// CHECK: SubclassOfGenericSuperclassWithURLField nil 45
|
|
}
|
|
#else
|
|
// Simulate the expected output.
|
|
print("SubclassOfGenericSuperclassWithURLField nil 45")
|
|
#endif
|