Skip to content

[5.0] Always give known-empty class properties a zero offset in the static layout #22739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

rjmccall
Copy link
Contributor

Field offset vectors are always filled out with either zero or the static layout's offset, depending on the metadata initialization strategy. This change means that the static layout's offset will only be non-zero for properties with a statically-known layout. Existing runtimes doing dynamic class layout assign class properties a zero offset if the field offset vector entry is zero and the property is zero-sized. So this effectively brings the compiler into accord with the runtime (for all newly-compiled Swift code, which will eventually be all Swift code because the current public releases of Swift 5 are not yet considered ABI-stable) and guarantees a zero value for the offset everywhere.

Since the runtime will agree with the compiler about the zero value of the offset, the compiler can continue to emit such offset variables as constant. The exception to this rule is if the class has non-fragile ObjC ancestry, in which case the ObjC runtime (which is not aware of this special rule for empty fields) will attempt to slide it along with everything else.

Fixes rdar://48031465, in which the FixedClassMetadataBuilder for a class with a legacy-fixed layout was writing a non-zero offset for an empty field into the field offset vector, causing the runtime to not apply the special case and thus to compute a non-zero offset, which it then attempted to copy into the global field offset variable, which the compiler had emitted as a true-constant zero.

This is the 5.0 version of #22738. It is not ABI-breaking, although it does establish a stronger ABI invariant that future runtimes (which will be able to assume that all code uses this rule) will be able to take advantage of.

@rjmccall rjmccall requested a review from a team as a code owner February 20, 2019 06:09
@rjmccall
Copy link
Contributor Author

@swift-ci Please test.

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - ab864ed4526b60082b39ef7b57ed99b6f9b3f1a7

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - ab864ed4526b60082b39ef7b57ed99b6f9b3f1a7

@rjmccall rjmccall force-pushed the empty-field-offset-variables-5.0 branch from ab864ed to b94fa98 Compare February 20, 2019 17:58
@rjmccall
Copy link
Contributor Author

@swift-ci Please test.

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - ab864ed4526b60082b39ef7b57ed99b6f9b3f1a7

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - ab864ed4526b60082b39ef7b57ed99b6f9b3f1a7

…layout.

Field offset vectors are always filled out with either zero or the static layout's offset, depending on the metadata initialization strategy.  This change means that the static layout's offset will only be non-zero for properties with a statically-known layout.  Existing runtimes doing dynamic class layout assign class properties a zero offset if the field offset vector entry is zero and the property is zero-sized.  So this effectively brings the compiler into accord with the runtime (for all newly-compiled Swift code, which will eventually be all Swift code because the current public releases of Swift 5 are not yet considered ABI-stable) and guarantees a zero value for the offset everywhere.

Since the runtime will agree with the compiler about the zero value of the offset, the compiler can continue to emit such offset variables as constant.  The exception to this rule is if the class has non-fragile ObjC ancestry, in which case the ObjC runtime (which is not aware of this special rule for empty fields) will attempt to slide it along with everything else.

Fixes rdar://48031465, in which the `FixedClassMetadataBuilder` for a class with a legacy-fixed layout was writing a non-zero offset for an empty field into the field offset vector, causing the runtime to not apply the special case and thus to compute a non-zero offset, which it then attempted to copy into the global field offset variable, which the compiler had emitted as a true-constant zero.
@rjmccall rjmccall force-pushed the empty-field-offset-variables-5.0 branch from b94fa98 to f9d1129 Compare February 20, 2019 22:58
@rjmccall
Copy link
Contributor Author

swift-5.0-branch still requires -enable-class-resilience to be passed at the -frontend level.

@rjmccall
Copy link
Contributor Author

@swift-ci Please test.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - b94fa984208b4fe68aa2a26af2fc8e6aa1b04f1e

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - b94fa984208b4fe68aa2a26af2fc8e6aa1b04f1e

@AnnaZaks AnnaZaks merged commit 5ff6d51 into swiftlang:swift-5.0-branch Feb 21, 2019
@rjmccall rjmccall deleted the empty-field-offset-variables-5.0 branch February 21, 2019 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants