Skip to content

[5.3] [metadata prespecialization] Zero trailing flags field. #31420

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

Conversation

nate-chandler
Copy link
Contributor

The important changes here are

[metadata prespecialization] Zero trailing flags.

Previously, the trailing flags field of runtime instantiated generic metadata for types which had prespecialization enabled were not zeroed. Consequently, the field always contained garbage. Often, metadata was instantiated on new (and so, zeroed) pages, so the garbage happened to be zero as is appropriate. However, when the metadata was instantiated on pages which had previously been dirtied, the garbage value would sometimes indicate that the metadata was canonical statically specialized. When that occurred, swift_checkMetadataState would incorrectly return a metadata state of complete, despite the fact that the metadata might not in fact be complete. As a result, the runtime was trafficking in incomplete metadata as if it were complete, resulting in various crashes that would arise from for example missing a witness table or a value witness table.

Here the problem is corrected. The trailing flags field of structs and enums that have the field is set to 0. For structs, this is accomplished by modifying the extra data pattern to exist not only when there is fixed type info for the type but also when the type is being prespecialized. For enums, this is achieved by modifying the metadata allocation function to do the zeroing.

rdar://problem/61465515

and

[IRGen] Corrected size of trailing flags field.

The struct and enum metadata scanners were both adding a pointer for the trailing flags field. That was only correct for 64-bit platforms. Instead, add an Int64.

Together, those two commits unlock reenabling metadata prespecialization for the stdlib.

Additionally, improved the debuggability of bad metadata records by first memsetting them to 0xAA on allocation in debug builds and secondly asserting that newly created records are not prespecialized. Mike Ash pointed out that the memsetting could be done in release builds as well by so long as the work if the MallocScribble environment variable is set; that change will be done in a follow-on commit.

The struct and enum metadata scanners were both adding a pointer for the
trailing flags field.  That was only correct for 64-bit platforms.
Instead, add an Int64.
Added an assertion that a generic metadata record that is instantiated
at runtime is not a prespecialized metadata record.
Previously, the trailing flags field of runtime instantiated generic
metadata for types which had prespecialization enabled were not zeroed.
Consequently, the field always contained garbage.  Often, metadata was
instantiated on new (and so, zeroed) pages, so the garbage happened to
be zero as is appropriate.  However, when the metadata was instantiated
on pages which had previously been dirtied, the garbage value would
sometimes indicate that the metadata was canonical statically
specialized.  When that occurred, swift_checkMetadataState would
incorrectly return a metadata state of complete, despite the fact that
the metadata might not in fact be complete.  As a result, the runtime
was trafficking in incomplete metadata as if it were complete, resulting
in various crashes that would arise from for example missing a witness
table or a value witness table.

Here the problem is corrected.  The trailing flags field of structs and
enums that have the field is set to 0.

For structs, this is accomplished by modifying the extra data pattern to
exist not only when there is fixed type info for the type but also when
the type is being prespecialized.  Specifically, the extra data for a
struct is, rather than an i32 array of field offsets, a struct
consisting of none, one, or both of the following: (1) the array of
field offsets, (2) the trailing flags.

Similarly, enums now have an extra data pattern which consists of none,
one, or both of the following: (1) the payload size, (2) the trailing
flags.  Enum metadata extra data setting was previously achieved by
customizing the metadata allocation function; that customization is now
eliminated, being replaced with the shared runtime code for copying
extra data into place, a modest code size savings.

rdar://problem/61465515
To facilitate debugging metadata records which are not properly
initialized, upon allocation fill them with a regular byte pattern
(0xAA) so that on subsequent inspection it is obvious if part of the
record is not initialized.
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler
Copy link
Contributor Author

@swift-ci please test windows platform

@nate-chandler nate-chandler merged commit 31d5385 into swiftlang:release/5.3 Apr 30, 2020
@nate-chandler nate-chandler deleted the generic-metadata-prespecialization-components/rdar61465515 branch April 30, 2020 01:06
@AnthonyLatsis AnthonyLatsis added swift 5.3 🍒 release cherry pick Flag: Release branch cherry picks labels Jan 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍒 release cherry pick Flag: Release branch cherry picks swift 5.3
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants