Преобразует ли LLVM методы Objective-C в встроенные функции? - PullRequest
13 голосов
/ 19 ноября 2011
  1. Может ли LLVM автоматически преобразовывать методы Objective-C во встроенные функции, когда это возможно?

    (т. Е. Является ли таким же производительным создание метода Objective-C для блока кода, который вы могли бы вставлять в строку?)

  2. Если LLVM не выполняет эту оптимизацию, почему бы и нет? Если да, (a) есть ли определенные настройки сборки, которые я должен установить для этого? (б) Как я могу определить, будет ли встроен метод Objective-C?

Ответы [ 3 ]

12 голосов
/ 19 ноября 2011

Нет, потому что невозможно знать в контексте среды выполнения Obj-C, можно ли выполнить такие оптимизации.Следует помнить, что методы Obj-C вызываются отправкой сообщения, и эти сообщения могут быть не просто синтаксисом [myObject doSomething].

Примите во внимание [obj performSelector:NSSelectorFromString(@"hello")] тот факт, что это может произойти, означает, что невозможно встроить какой-либо метод.

Существует также цепочка событий, которая происходит, когда сообщение полученоКласс, эти события могут перенаправить, или даже изменить сообщение, которое отправляется.Это происходит прозрачно под отправкой сообщения.

9 голосов
/ 30 ноября 2011

Давайте на минутку предположим, что компилятор включает метод:

@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.

В только раз я мог видеть, что это возможно, если бы был какой-то способ аннотировать метод как не подлежащий переопределению. Но нет способа сделать это , так что эта проблема спорная. И даже тогда это все равно будет плохой идеей; то, что компилятор не позволяет вам этого делать, не означает, что вы не можете обойти его во время выполнения. И снова вы столкнетесь с проблемами.

9 голосов
/ 19 ноября 2011

Нет. Важной особенностью Objective-C является то, что отправка сообщений (помните, что в Obj-C вы отправляете сообщение , вы не вызываете метод ) происходит динамически во время выполнения, а не во время компиляции.

Из-за этого отправка сообщений в Obj-C всегда будет немного медленнее, чем простой вызов функции (даже если функция не встроена).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...