Does LLVM convert Objective-C methods to inline fu

2019-01-18 22:35发布

问题:

  1. Does LLVM automatically convert Objective-C methods to inline functions when possible?

    (I.e., is it just as performant to create an Objective-C method for a block of code that you could otherwise paste inline?)

  2. If LLVM doesn't perform this optimization, why not? If it does, (a) are there certain build settings I must set for this to happen? (b) How can I tell if an Objective-C method will be inlined?

回答1:

No, because its impossible to know in the context of the Obj-C runtime if those kind of optimizations can be performed. The thing to remember is that Obj-C methods are invoked by a message send, these messages can come from more than just the [myObject doSomething] syntax.

Consider [obj performSelector:NSSelectorFromString(@"hello")] the fact that this can happen means that it would be impossible to ever inline any method.

There is also a chain of events that happens when a message is received by a class, these events can reroute, or even change the message that is being sent. This happens transparently underneath the message send.



回答2:

No. It is an essential feature of Objective-C that message dispatch (remember that in Obj-C you send a message, you don't call a method) happens dynamically at runtime, not at compile time.

Because of this, a message dispatch in Obj-C will always be a little slower than a pure function call (even if the function is not inlined).



回答3:

Let's assume for a moment that the compiler inlines a method:

@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

so that -doBar essentially becomes:

- (void)doBar {
  [self doAwesomeStuff];
  {
    NSLog(@"doing foo!");
  }
}

Awesome, that seems like it'd be faster, right? We save ourselves a whole dozen instructions by not calling objc_msgSend. So you package this up and post it online as a .a file.

NSCleverCoder comes along and says "but I want doFoo to do a little bit more", so he does:

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

When he tries to run this, it never gets called, because AwesomeClass never actually invokes the -doFoo method.

"But," you say, "this is a contrived example!"

No, it's not. In Objective-C, it is perfectly legal to do this at any point in the development or execution of an app. I can do this when writing the code. Heck, I can even do this at runtime by using objc_allocateClassPair and class_addMethod to dynamically create a subclass and add a method override.

I can also swizzle method implementations. Don't like the existing implementation of -doFoo? That's cool; replace it with your own. Oh wait; if the method was inlined, your new implementation would never get called, because -doBar is never actually invoking the -doFoo method.

The only time I could see this being possible is if there were some sort of way to annotate a method as being un-overridable. But there's no way to do that, so that issue is moot. And even then, it would still be a bad idea; just because the compiler doesn't let you do it doesn't mean you can't still work around it at runtime. And again, you'd run in to problems.