2011-11-19 105 views
13
  1. 如果可能,LLVM是否自动将Objective-C方法转换为内联函数?LLVM是否将Objective-C方法转换为内联函数?

    (即,它是同样高性能创建的代码块,你可以粘贴,否则内嵌Objective-C的方法是什么?)

  2. 如果LLVM不执行该优化,为什么不呢?如果确实如此,(a)是否有某些构建设置需要设置才能发生? (b)如何判断Objective-C方法是否内联?

回答

12

没有,因为它不可能知道对象 - C运行时的情况下,如果能够执行这些类型的优化。需要记住的是Obj-C方法是由消息发送调用的,这些消息可能来自不仅仅是[myObject doSomething]语法。

考虑[obj performSelector:NSSelectorFromString(@"hello")]事实上,这可能发生意味着不可能内联任何方法。

当一个类收到消息时,也会发生一系列事件,这些事件可以重新路由,甚至可以更改正在发送的消息。这在消息发送下透明地发生。

+0

LLVM为什么不能取代常规的调用,例如'[obj x]; obj.x'和'performSelector'调用,例如'[obj performSelector:x_sel]'等等,方法体'x'?而且,为什么它不能检查像'forwardInvocation:'这样的方法的实现来确定它是否应该内联?来吧LLVM,更聪明! :) – ma11hew28

+7

因为它们可以在运行时轻松地换出。我可以在3或4行运行时代码中更改任何方法的实现。 –

9

号是Objective-C中的一个基本特征是信息调度(记住,在对象 - 你发送邮件,你不呼叫的方法)发生在运行时动态,不能在编译时间。因此,Obj-C中的消息分派总是比纯函数调用慢一点(即使该函数未内联)。

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!"); 
    } 
} 

真棒,这似乎是它会是更快的,对不对?我们通过不致电节省了十多条指令。因此,您将其打包并在线发布为.a文件。

NSCleverCoder出现了,说:“但我想doFoo多做一点点”,所以他:

@interface SuperAwesomeClass : AwesomeClass @end 
@implementation SuperAwesomeClass 
- (void)doFoo { 
    NSLog(@"doing more foo!"); 
    [super doFoo]; 
} 
@end 

当他尝试运行此,它永远不会被调用,因为AwesomeClass从来没有实际上调用-doFoo方法。

“但是,”你说,“这是一个人为的例子!”

不,不是。在Objective-C中,在开发或执行应用程序的任何时候完成此操作都是合法的。编写代码时我可以这样做。哎呀,我甚至可以在运行时使用objc_allocateClassPairclass_addMethod来动态创建子类并添加方法覆盖。

我也可以调试方法的实现。不喜欢-doFoo的现有实施?这很酷;用你自己的替换它。等一下;如果方法被内联,您的新实现将永远不会被调用,因为-doBar实际上从未调用-doFoo方法。

只有时间我可以看到这是可能的是,如果有某种方式来注释方法是不可覆盖的。 But there's no way to do that,所以这个问题是没有意义的。和即使然后,它仍然是一个坏主意;仅仅因为编译器不会让你这样做并不意味着你不能在运行时解决它。再一次,你会遇到问题。

+0

我想我只是想编译器可以检测到这样的情况下,方法被重写的方法中调用,并将其插入重写的方法...但是,我可以看到如何编译器将不得不相当聪明去做。尽管如此,ARC还是非常了不起...也许他们可以为LLVM添加另一个很酷的功能,它知道如何内联方法。 – ma11hew28