Подтвердить что ты не робот

Использует ли LLVM методы Objective-C для встроенных функций?

  • Может ли LLVM автоматически преобразовывать методы Objective-C в встроенные функции, если это возможно?

    (I.e., так же просто, как создать метод Objective-C для блока кода, который вы могли бы вставить в свою очередь?)

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

4b9b3361

Ответ 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. Но нет способа сделать это, так что этот вопрос является спорным. И даже тогда это все равно будет плохой идеей; просто потому, что компилятор не позволяет вам это делать, это не значит, что вы не можете работать с ним во время выполнения. И снова вы столкнулись с проблемами.