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?)
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.