-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Add new runtime functions for handling dependencies when initializing class metadata #22386
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
Add new runtime functions for handling dependencies when initializing class metadata #22386
Conversation
Note that I've called out a couple of suspicious places where we are requesting abstract metadata for superclasses but probably need to be requesting something more complete.
5dfa8e1
to
887564d
Compare
@swift-ci Please test. |
It looks like you didn't add compatibility override slots for the new entry points in this variation. |
I don't think there were compatibility override slots for the existing entry points. |
887564d
to
a074bc2
Compare
@swift-ci Please test. |
1 similar comment
@swift-ci Please test. |
Ah, you're right, I had assumed that they were because of the other changes. Nevermind. Aside from this issue it LGTM. |
@@ -808,6 +808,34 @@ FUNCTION(UpdateClassMetadata, | |||
SizeTy->getPointerTo()), | |||
ATTRS(NoUnwind)) | |||
|
|||
// struct FieldInfo { size_t Size; size_t AlignMask; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a comment fix, but what is this "FieldInfo"? Is it supposed to be the "TypeLayout" type mentioned in the comment's function signature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I just copied that comment from another declaration, but I can fix it.
Private testing shows that the actual runtime code works. |
I'll do Brent's request in the compiler PR. |
In our initial approach for resolving metadata dependency cycles with classes, non-transitively complete superclass metadata was fetched by the subclass's metadata completion function and passed to `swift_initClassMetadata`. That could mean generating quite a lot of code in the completion function, and so we fairly recently changed it so that `swift_initClassMetadata` instead fetched the superclass metadata via a demangling. Unfortunately, the metadata demangler only fetches _abstract_ metadata by default, and class metadata cannot be considered even non-transitively complete when its superclass reference not at that stage. If the superclass metadata is being completed on one thread, and a subclass is being completed on another, and the subclass installs the incomplete superclass metadata in its superclass field and attempts to register the subclass with the Objective-C runtime, the runtime may crash reading the incompletely-initialized superclass. The proper fix is to make `swift_initClassMetadata` fetch non-transitively complete metadata for the superclass, delaying completion if that metadata is unavailable. Unfortunately, that can't actually be implemented on top of `swift_initClassMetadata` because that function has no means of reporting an unsatisfied dependency to its caller, and we can no longer simply change its signature without worrying about a small of internal code that might still be using it. We cannot simply perform a blocking metadata request in `swift_initClassMetadata` because it is deeply problematic to block within a metadata completion function. The solution is therefore to add a `swift_initClassMetadata2` which has the ability to report unsatisfied dependencies. That was done in swiftlang#22386; this patch builds on that by teaching the compiler to generate code to actually use it. It is therefore not safe to use this patch if you might be running on an OS that only provides the old runtime function, but that should be a temporary Apple-internal problem. Fixes rdar://47549859.
In our initial approach for resolving metadata dependency cycles with classes, non-transitively complete superclass metadata was fetched by the subclass's metadata completion function and passed to `swift_initClassMetadata`. That could mean generating quite a lot of code in the completion function, and so we fairly recently changed it so that `swift_initClassMetadata` instead fetched the superclass metadata via a demangling. Unfortunately, the metadata demangler only fetches _abstract_ metadata by default, and class metadata cannot be considered even non-transitively complete when its superclass reference not at that stage. If the superclass metadata is being completed on one thread, and a subclass is being completed on another, and the subclass installs the incomplete superclass metadata in its superclass field and attempts to register the subclass with the Objective-C runtime, the runtime may crash reading the incompletely-initialized superclass. The proper fix is to make `swift_initClassMetadata` fetch non-transitively complete metadata for the superclass, delaying completion if that metadata is unavailable. Unfortunately, that can't actually be implemented on top of `swift_initClassMetadata` because that function has no means of reporting an unsatisfied dependency to its caller, and we can no longer simply change its signature without worrying about a small of internal code that might still be using it. We cannot simply perform a blocking metadata request in `swift_initClassMetadata` because it is deeply problematic to block within a metadata completion function. The solution is therefore to add a `swift_initClassMetadata2` which has the ability to report unsatisfied dependencies. That was done in swiftlang#22386; this patch builds on that by teaching the compiler to generate code to actually use it. It is therefore not safe to use this patch if you might be running on an OS that only provides the old runtime function, but that should be a temporary Apple-internal problem. Fixes rdar://47549859.
This is part of the fix for the race condition identified in rdar://47549859. The fix in #22381 is too naive because we cannot stage it in; instead we need to make a runtime-only change to add new runtime functions, then switch the compiler to use them only when the compiler entrypoints can be safely presumed to exist.