-
Notifications
You must be signed in to change notification settings - Fork 10.5k
IRGen: Don't eagerly initialize NSCoding conformers on startup on new deployment targets #23413
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
IRGen: Don't eagerly initialize NSCoding conformers on startup on new deployment targets #23413
Conversation
@jrose-apple Before I update the tests and so on -- does this make sense to you? |
Eagerly registering a class also runs any |
@jrose-apple I understand where you're coming from but as far as I can tell the only effect of the attribute is to add the class to the vector in IRGen. IRGen emits a static constructor, which calls the metadata accessor for each eager class which I assume triggers the call to |
@jrose-apple I went and looked and it turns out we have two attributes:
|
I was thinking that we may have a use for the |
The two attributes have basically the same effect for a class with fixed metadata; it's just that the latter is something the Objective-C runtime handles natively and the former uses a static constructor. |
@jrose-apple Right. We don't actually ever emit StaticInitializeObjCMetadataAddr on classes without generic ancestry, since those could be found by name on the old runtime anyway. I'm not proposing renaming or removing the attribute, just not adding it on classes conforming to NSCoding when your deployment target is sufficiently new. |
I'm in favor of "don't add the attribute on classes conforming to NSCoding", but this patch doesn't do that; it ignores the attribute in IRGen instead, no matter why it was added. |
@jrose-apple Ok, glad we're on the same page then. |
12732a3
to
1a54266
Compare
@swift-ci Please smoke test |
include/swift/Basic/LangOptions.h
Outdated
// - iOS 12.2 | ||
// - tvOS 12.2 | ||
// - watchOS 5.2 | ||
bool doesPlatformSupportObjCGetClassHook() const; |
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.
Nitpick: these should be "target" or "deployment target" or "minimum deployment target", not "platform". "Platform" doesn't include a version number.
if (Target.isWatchOS()) | ||
return !Target.isOSVersionLT(5, 2); | ||
|
||
return false; |
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.
Can you leave a comment noting that this allows us to run ObjC tests on non-Apple platforms? That's the main reason to leave it this way instead of asserting, I think.
@@ -5039,7 +5043,8 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc, | |||
if (auto classDecl = dc->getSelfClassDecl()) { | |||
if (Context.LangOpts.EnableObjCInterop && | |||
isNSCoding(conformance->getProtocol()) && | |||
!classDecl->isGenericContext()) { | |||
!classDecl->isGenericContext() && | |||
!classDecl->hasClangNode()) { |
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.
When does this come up?
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.
Retroactive conformance of imported class to NSCoding. We already checked for hasClangNode() before, but I moved it.
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.
*shrug* All right. It's true that those won't have unstable names either.
@@ -1,7 +1,6 @@ | |||
// RUN: %empty-directory(%t) | |||
// RUN: %target-build-swift %s -module-name=test -DENCODE -o %t/encode | |||
// RUN: %target-build-swift %s -module-name=test -o %t/decode | |||
// RUN: %target-build-swift %s -module-name=test -Xfrontend -disable-llvm-optzns -emit-ir | %FileCheck -check-prefix=CHECK-IR %s | |||
// RUN: %target-run %t/encode %t/test.arc | |||
// RUN: plutil -p %t/test.arc | %FileCheck -check-prefix=CHECK-ARCHIVE %s | |||
// RUN: %target-run %t/decode %t/test.arc | %FileCheck %s |
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.
This is an execution test; would it make sense to do it both the old way and the new way if we're on a new enough OS?
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.
(I'm not even 100% sure how to write such a test, but…)
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.
I can build the test with an old and new deployment target, and in the new deployment target case, add a runtime check that skips the test.
1a54266
to
a1363ab
Compare
@swift-ci Please smoke test |
@swift-ci Please test source compatibility |
…gets If a class does not have a custom @objc name, objc_getClass() can find it at runtime by calling the Swift runtime's metadata demangler hook. This avoids the static initializer on startup. If the class has a custom runtime name we still need the static initializer unfortunately. Fixes <rdar://problem/49660515>.
a1363ab
to
6d7d13f
Compare
@swift-ci Please smoke test |
1 similar comment
@swift-ci Please smoke test |
@swift-ci Please smoke test macOS |
If objc_getClass() can realize arbitrary Swift classes there's no reason
to generate the static constructor.
Fixes rdar://problem/49660515.