summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGenObjC
diff options
context:
space:
mode:
authorPierre Habouzit <phabouzit@apple.com>2020-01-14 18:56:26 -0800
committerPierre Habouzit <phabouzit@apple.com>2020-01-14 19:48:33 -0800
commitd18fbfc09720009c0dc6a1ddf315402ee0a7751d (patch)
treeac2281f464f0bf4e6df2dc53a5ac06f879519d96 /clang/test/CodeGenObjC
parent0dbcb3639451a7c20e2d5133b459552281e64455 (diff)
downloadbcm5719-llvm-d18fbfc09720009c0dc6a1ddf315402ee0a7751d.tar.gz
bcm5719-llvm-d18fbfc09720009c0dc6a1ddf315402ee0a7751d.zip
Relax the rules around objc_alloc and objc_alloc_init optimizations.
Today the optimization is limited to: - `[ClassName alloc]` - `[self alloc]` when within a class method However it means that when code is written this way: ``` @interface MyObject - (id)copyWithZone:(NSZone *)zone { return [[self.class alloc] _initWith...]; } @end ``` ... then the optimization doesn't kick in and `+[NSObject alloc]` ends up in IMP caches where it could have been avoided. It turns out that `+alloc` -> `+[NSObject alloc]` is the most cached SEL/IMP pair in the entire platform which is rather silly). There's two theoretical risks allowing this optimization: 1. if the receiver is nil (which it can't be today), but it turns out that `objc_alloc()`/`objc_alloc_init()` cope with a nil receiver, 2. if the `Clas` type for the receiver is a lie. However, for such a code to work today (and not fail witn an unrecognized selector anyway) you'd have to have implemented the `-alloc` **instance method**. Fortunately, `objc_alloc()` doesn't assume that the receiver is a Class, it basically starts with a test that is similar to `if (receiver->isa->bits & hasDefaultAWZ) { /* fastpath */ }`. This bit is only set on metaclasses by the runtime, so if an instance is passed to this function by accident, its isa will fail this test, and `objc_alloc()` will gracefully fallback to `objc_msgSend()`. The one thing `objc_alloc()` doesn't support is tagged pointer instances. None of the tagged pointer classes implement an instance method called `'alloc'` (actually there's a single class in the entire Apple codebase that has such a method). Differential Revision: https://reviews.llvm.org/D71682 Radar-Id: rdar://problem/58058316 Reviewed-By: Akira Hatanaka Signed-off-by: Pierre Habouzit <phabouzit@apple.com>
Diffstat (limited to 'clang/test/CodeGenObjC')
-rw-r--r--clang/test/CodeGenObjC/objc-alloc-init.m11
1 files changed, 10 insertions, 1 deletions
diff --git a/clang/test/CodeGenObjC/objc-alloc-init.m b/clang/test/CodeGenObjC/objc-alloc-init.m
index c5c1a763b7c..8370202748e 100644
--- a/clang/test/CodeGenObjC/objc-alloc-init.m
+++ b/clang/test/CodeGenObjC/objc-alloc-init.m
@@ -22,21 +22,30 @@ void f() {
}
@interface Y : X
++(Class)class;
+(void)meth;
-(void)instanceMeth;
@end
@implementation Y
++(Class)class {
+ return self;
+}
+(void)meth {
[[self alloc] init];
// OPTIMIZED: call i8* @objc_alloc_init(
// NOT_OPTIMIZED: call i8* @objc_alloc(
}
++ (void)meth2 {
+ [[[self class] alloc] init];
+ // OPTIMIZED: call i8* @objc_alloc_init(
+ // NOT_OPTIMIZED: call i8* @objc_alloc(
+}
-(void)instanceMeth {
// EITHER-NOT: call i8* @objc_alloc
// EITHER: call {{.*}} @objc_msgSend
// EITHER: call {{.*}} @objc_msgSend
- [[self alloc] init];
+ [[(id)self alloc] init];
}
@end
OpenPOWER on IntegriCloud