Files
swift-mirror/test/Runtime/subclass_instance_start_adjustment.swift
Mike Ash a71eaf15db [Runtime] Don't shrink class InstanceStart when initing field offset vectors.
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
2024-02-28 10:49:42 -05:00

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