LLVM是否会在可能的情况下自动将Objective-C方法转换为内联函数?
(即,是否能够为一段代码创建一个Objective-C方法,否则你可以粘贴内联?)
如果LLVM没有执行此优化,为什么不呢?如果是,(a)是否有必须为此设置的某些构建设置? (b)如何判断是否内联Objective-C方法?
答案 0 :(得分:12)
不,因为在Obj-C运行时的上下文中无法知道是否可以执行这些优化。要记住的是Obj-C方法是由消息发送调用的,这些消息不仅仅来自[myObject doSomething]
语法。
考虑[obj performSelector:NSSelectorFromString(@"hello")]
这可能发生的事实意味着不可能内联任何方法。
当类接收到消息时,也会发生一系列事件,这些事件可以重新路由,甚至更改正在发送的消息。这在邮件发送的下方透明地发生。
答案 1 :(得分:9)
没有。 Objective-C的一个基本特征是消息调度(记住在Obj-C中你发送消息,你没有调用方法)在运行时动态发生,而不是在编译时。
因此,Obj-C中的消息调度总是比纯函数调用慢一点(即使函数没有内联)。
答案 2 :(得分:9)
让我们暂时假设编译器内联一个方法:
@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
以便-doBar
基本上成为:
- (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
方法。
唯一时间我可以看到这是可能的,如果有某种方法可以将方法注释为不可覆盖的方法。 But there's no way to do that,这个问题没有实际意义。而即便如此,它仍然是一个坏主意;只是因为编译器不允许你这样做并不意味着你不能在运行时解决它。而且,你会遇到问题。