swift
425c1900 - Restore initializing entry points for @objc convenience initializers (#21815)

Commit
6 years ago
Restore initializing entry points for @objc convenience initializers (#21815) This undoes some of Joe's work in 8665342 to add a guarantee: if an @objc convenience initializer only calls other @objc initializers that eventually call a designated initializer, it won't result in an extra allocation. While Objective-C /allows/ returning a different object from an initializer than the allocation you were given, doing so doesn't play well with some very hairy implementation details of compiled nib files (or NSCoding archives with cyclic references in general). This guarantee only applies to (1) calling `self.init` (2) where the delegated-to initializer is @objc because convenience initializers must do dynamic dispatch when they delegate, and Swift only stores allocating entry points for initializers in a class's vtable. To dynamically find an initializing entry point, ObjC dispatch must be used instead. (It's worth noting that this patch does NOT check that the calling initializer is a convenience initializer when deciding whether to use ObjC dispatch for `self.init`. If we ever add peer delegation to designated initializers, which is totally a valid feature, that should use static dispatch and therefore should not go through objc_msgSend.) This change doesn't /always/ result in fewer allocations; if the delegated-to initializer ends up returning a different object after all, the original allocation was wasted. Objective-C has the same problem (one of the reasons why factory methods exist for things like NSNumber and NSArray). We do still get most of the benefits of Joe's original change. In particular, vtables only ever contain allocating initializer entry points, never the initializing ones, and never /both/ (which was a thing that could happen with 'required' before). rdar://problem/46823518
Author
Parents
Loading