-
Может ли LLVM автоматически преобразовывать методы Objective-C в встроенные функции, если это возможно?
(I.e., так же просто, как создать метод Objective-C для блока кода, который вы могли бы вставить в свою очередь?)
-
Если LLVM не выполняет эту оптимизацию, почему бы и нет? Если это так, (а) есть ли определенные настройки сборки, которые я должен установить для этого? (b) Как я могу определить, будет ли метод Objective-C встроен?
Использует ли LLVM методы Objective-C для встроенных функций?
Ответ 1
Нет, потому что его невозможно узнать в контексте времени выполнения Obj-C, если такие оптимизации могут быть выполнены. Следует помнить, что методы Obj-C вызываются отправкой сообщений, эти сообщения могут поступать не только из синтаксиса [myObject doSomething]
.
Рассмотрим [obj performSelector:NSSelectorFromString(@"hello")]
тот факт, что это может произойти, означает, что было бы невозможно когда-либо внедрить какой-либо метод.
Существует также цепочка событий, которая возникает, когда сообщение принимается классом, эти события могут перенаправлять или даже изменять отправленное сообщение. Это происходит прозрачно под отправкой сообщения.
Ответ 2
Нет. Это важная функция Objective-C отправки сообщения (помните, что в Obj-C вы отправляете сообщение, вы не вызываете метод) происходит динамически во время выполнения, а не во время компиляции.
Из-за этого отправка сообщения в Obj-C всегда будет немного медленнее, чем вызов чистой функции (даже если функция не включена).
Ответ 3
Предположим на мгновение, что компилятор заключает в себе метод:
@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
для динамического создания подкласса и добавления переопределения метода.
Я также могу использовать методы реализации swizzle. Не нравится существующая реализация -doFoo
? Это здорово; замените его своим. О, подождите; если метод был встроен, ваша новая реализация никогда не будет вызвана, потому что -doBar
никогда не вызывает метод -doFoo
.
Время только, которое я видел, это возможно, если бы какой-то способ аннотировать метод как un-overridable. Но нет способа сделать это, так что этот вопрос является спорным. И даже тогда это все равно будет плохой идеей; просто потому, что компилятор не позволяет вам это делать, это не значит, что вы не можете работать с ним во время выполнения. И снова вы столкнулись с проблемами.