-
LLVM是否会在可能的情况下自动将Objective-C方法转换为内联函数?
(也就是说,为一块代码创建一个Objective-C方法,否则可以内联粘贴,这是否同样具有性能?(
-
如果LLVM不执行此优化,为什么不呢?如果是,(a(我是否必须设置某些构建设置才能实现这一点?(b( 如何判断Objective-C方法是否会内联?
否,因为在Obj-C运行时的上下文中不可能知道是否可以执行这些类型的优化。需要记住的是,Obj-C方法是由消息发送调用的,这些消息可能不仅仅来自[myObject doSomething]
语法。
以[obj performSelector:NSSelectorFromString(@"hello")]
为例,这种情况可能发生,这意味着不可能内联任何方法。
当类接收到消息时,还会发生一系列事件,这些事件可以重新路由,甚至更改正在发送的消息。这在消息发送的下面透明地发生。
否。Objective-C的一个基本特性是消息调度(请记住,在Obj-C中,您发送消息,而不是调用方法(在运行时动态发生,而不是在编译时。
因此,Obj-C中的消息调度总是比纯函数调用慢一点(即使函数没有内联(。
让我们假设编译器内联了一个方法:
@implementation AwesomeClass
- (void)doFoo OBJC_INLINE { // or some way to indicate "this is an inline method"
NSLog(@"doing foo!");
}
- (void)doBar {
[self doAwesomeStuff];
[self doFoo];
}
@end
使得CCD_ 3实质上变为:
- (void)doBar {
[self doAwesomeStuff];
{
NSLog(@"doing foo!");
}
}
太棒了,看起来会更快,对吧?通过不调用objc_msgSend
,我们节省了整整十几条指令。所以你把它打包后作为.a文件发布到网上。
NSCleverCoder走了过来,说"但我想让doFoo
做得更多",所以他做了:
@interface SuperAwesomeClass : AwesomeClass @end
@implementation SuperAwesomeClass
- (void)doFoo {
NSLog(@"doing more foo!");
[super doFoo];
}
@end
当他尝试运行这个时,它永远不会被调用,因为AwesomeClass
从来没有实际调用过-doFoo
方法。
"但是,"你说,"这是一个人为的例子!">
不,不是。在Objective-C中,在应用程序开发或执行的任何时候这样做都是完全合法的。我可以在编写代码时做到这一点。见鬼,我甚至可以在运行时使用objc_allocateClassPair
和class_addMethod
动态创建一个子类并添加一个方法覆盖来实现这一点。
我还可以快速处理方法实现。不喜欢-doFoo
的现有实现?这很酷;把它换成你自己的。哦,等等;如果该方法是内联的,那么您的新实现将永远不会被调用,因为-doBar
实际上从未调用过-doFoo
方法。
如果有某种方法可以将方法注释为不可重写,那么我唯一能看到这一点的时间是。但没有办法做到这一点,所以这个问题没有实际意义。而且即使是,这仍然是个坏主意;编译器不允许你这样做并不意味着你不能在运行时处理它。再说一遍,你会遇到问题。