2012-05-03 3 views
14

Я прочитал Transitioning to ARC Release Notes в разделе «Резюме». Они сказали:Возможно ли увидеть код, сгенерированный ARC во время компиляции?

ARC работает, добавляя код во время компиляции, чтобы обеспечить живые объекты столько, сколько необходимо, но больше не нужно. Концептуально, он следует тем же соглашениям управления памятью, что и ручной подсчет ссылок (описанный в Руководстве по программированию расширенного управления памятью), добавив для вас соответствующие вызовы управления памятью .

В для компилятора для того, чтобы генерировать правильный код

Интересно, что результат, что ARC исправлен наш код.

Мой вопрос: Можем ли мы увидеть изменение? (В срок Alloc, сохранить, назначить или освободить .Не уровень сборки!)

Причина: Потому что я думаю, что это хорошо, чтобы увидеть код лучшей практики в развитии старой традиции без режима ARC.

+1

Для исследования, я имею в виду «развитие старой традиции», это о том, как мы можем правильно распределять, сохранять, назначать или выпускать их. Я также не хотел бы жестко кодировать детали сборки :-). – Sakares

+0

Вы можете просто прочитать документацию, связанную со статьей, которую вы цитируете, ARC делает то же самое, что описано в этой статье. Прочтите раздел «Политика управления памятью», чтобы начать, большинство правил ARC для ежедневного программирования получены оттуда. https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html –

+0

Возможный дубликат [Просмотр, где ARC вставляет сохранение и релизы] (http://stackoverflow.com/questions/8812098/see-where-arc-is-inserting-retain-and-releases) –

ответ

25

ARC в clang не работает, переписывая код из ObjC в ObjC, но выдавая дополнительный бит LLVM сохранения/выпуска во время кода-gen. Это означает, что невозможно понять, как компилятор «исправит» его, не перейдя на уровень LLVM IR/assembly.


Если АРК испускает LLVM, как битовый код вы сказали. Это сделано для этой цели, которая использует меньше времени в процессе компиляции? (менее сложный код ObjC, меньше заголовочный файл?)

Всегда лучше, если компилятор может уменьшить количество проходов через код.


Можете ли вы показать мне пример или утилиты, которые показывают код на уровне сборки?

Чтобы получить код сборки, вы можете либо

  1. Сформировать сборку непосредственно от компилятора. В командной строке добавьте флаг -S при вызове компилятора. Результатом является файл .S, содержащий код сборки. В проекте Xcode откройте файл исходного кода, затем перейдите к . Продукт (в строке меню) → Создать выходСборочный файл.

  2. Сгенерировать файл объекта, а затем разобрать его. Встроенная команда otool -tvV <file> может выполнить разборку, и есть дополнительные инструменты, такие как otx (бесплатно) или IDA (бесплатно для оценки).

Я предпочитаю маршрут 2, потому что он генерирует меньше мусора, и инструмент разборки может быть сконфигурирован для получения более полезной информации.В любом случае, с помощью любого метода вам нужно будет прочитать код сборки.

Возьмите этот код, например:

- (BOOL)application:(UIApplication*)application 
     didFinishLaunchingWithOptions:(NSDictionary*)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.window.backgroundColor = [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

После компиляции следующей сборки будет производиться (анализировались с помощью IDA):

 
-[SomeAppDelegate application:didFinishLaunchingWithOptions:]: 
    push  {r4-r7,lr} 
    add  r7, sp, #0xC 
    str.w  r8, [sp,-#0x4]! 
    sub  sp, sp, #0x18 
    movw  r1, #(0x343c - 0x2574)  ; @selector(alloc) 
    mov  r8, r0 
    movt.w  r1, #0 
    mov  r0, (0x3464 - 0x2576)  ; _OBJC_CLASS_$_UIWindow 
    add  r1, pc 
    add  r0, pc 
    ldr  r1, [r1] 
    ldr  r0, [r0] 
    blx  _objc_msgSend 
    mov  r1, (0x3440 - 0x258e)  ; @selector(mainScreen) 
    mov  r6, r0 
    movw  r0, #(0x3468 - 0x2594)  ; _OBJC_CLASS_$_UIScreen 
    add  r1, pc 
    movt.w  r0, #0 
    add  r0, pc 
    ldr  r1, [r1] 
    ldr  r0, [r0] 
    blx  _objc_msgSend 
    mov  r7, r7 
    blx  _objc_retainAutoreleasedReturnValue 
    mov  r5, r0 
    cbz  r5, L25ba 
    movw  r0, #(0x3444 - 0x25b2)  ; @selector(bounds) 
    mov  r1, r5 
    movt.w  r0, #0 
    add  r0, pc 
    ldr  r2, [r0] 
    add  r0, sp, #0x8 
    blx  _objc_msgSend_stret 
    b   L25c4 

L25ba: 
    add  r0, sp, #0x8 
    vmov.i32 q8, #0x80 
    vstmia  r0, {d16-d17} 

L25c4: 
    mov  r1, (0x3448 - 0x25d2)  ; @selector(initWithFrame:) 
    ldr  r0, [sp,#0x10] 
    add  r1, pc 
    ldr  r2, [sp,#0x8] 
    ldr  r3, [sp,#0xc] 
    ldr  r4, [sp,#0x14] 
    stmea.w sp, {r0,r4} 
    mov  r0, r6 
    ldr  r1, [r1] 
    blx  _objc_msgSend 
    mov  r4, r0 
    mov  r0, (0x344c - 0x25F2)  ; @selector(setWindow:) 
    mov  r2, r4 
    add  r0, pc 
    ldr  r1, [r0] 
    mov  r0, r8 
    blx  _objc_msgSend 
    mov  r0, r4 
    blx  _objc_release 
    mov  r0, r5 
    blx  _objc_release 
    mov  r0, (0x3450 - 0x2610)  ; @selector(window) 
    add  r0, pc 
    ldr  r5, [r0] 
    mov  r0, r8 
    mov  r1, r5 
    blx  _objc_msgSend 
    mov  r7, r7 
    blx  _objc_retainAutoreleasedReturnValue 
    mov  r1, (0x3454 - 0x2630)  ; @selector(whiteColor) 
    mov  r6, r0 
    movw  r0, #(0x346C - 0x2636)  ; _OBJC_CLASS_$_UIColor 
    add  r1, pc 
    movt.w  r0, #0 
    add  r0, pc 
    ldr  r1, [r1] 
    ldr  r0, [r0] 
    blx  _objc_msgSend 
    mov  r7, r7 
    blx  _objc_retainAutoreleasedReturnValue 
    mov  r4, r0 
    mov  r0, (0x3458 - 0x2652)  ; @selector(setBackgroundColor:) 
    mov  r2, r4 
    add  r0, pc 
    ldr  r1, [r0] 
    mov  r0, r6 
    blx  _objc_msgSend 
    mov  r0, r4 
    blx  _objc_release 
    mov  r0, r6 
    blx  _objc_release 
    mov  r0, r8 
    mov  r1, r5 
    blx  _objc_msgSend 
    mov  r7, r7 
    blx  _objc_retainAutoreleasedReturnValue 
    mov  r4, r0 
    mov  r0, (0x345C - 0x2680)  ; @selector(makeKeyAndVisible) 
    add  r0, pc 
    ldr  r1, [r0] 
    mov  r0, r4 
    blx  _objc_msgSend 
    mov  r0, r4 
    blx  _objc_release 
    movs  r0, #1 
    add  sp, sp, #0x18 
    ldr.w  r8, [sp], #4 
    pop  {r4-r7,pc} 

Не вдаваясь в подробности, вы можете видеть, что есть много _objc_release и _objc_retainAutoreleasedReturnValue. Это то, что ARC вставляет в код-gen. Декомпиляция его вручную, мы получим:

UIScreen* r5 = objc_retainAutoreleasedReturnValue([UIScreen mainScreen]); 
CGRect sp8 = r5 != nil ? [r5 bounds] : CGRectZero; 
UIWindow* r4 = [[UIWindow alloc] initWithFrame:sp8]; 
[self setWindow:r4]; 
objc_release(r4); 
objc_release(r5); 

UIWindow* r6a = objc_retainAutoreleasedReturnValue([self window]) 
UIColor* r4a = objc_retainAutoreleasedReturnValue([UIColor whiteColor]) 
[r6a setBackgroundColor:r4a]; 
objc_release(r4a); 
objc_release(r6a); 

UIWindow* r4b = objc_retainAutoreleasedReturnValue([self window]) 
[r4b makeKeyAndVisible]; 
objc_release(r4b); 

return 1; 

, который так же, как то, что описывает ссылку @c roald «s.

+0

Кажется, что вы сказали. Как вы думаете об испускании битового кода LLVM на уровне сборки, быстро компилируете? – Sakares

+0

@Jojas: Извините, я не понимаю, о чем вы говорите, быстро компилируете? – kennytm

+0

Я хотел бы спросить ваше мнение, если ARC испускает бит-код LLVM, как вы сказали. Это сделано для этой цели, которая использует меньше времени в процессе компиляции? (менее сложный код ObjC, меньше заголовочный файл?) – Sakares

2

Майк Зола имеет очень освещающее обсуждение реализации ARC здесь: http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

Он обсуждает его на уровне вставки вызовов функций C (objc_retain(), objc_release(), objc_retainAutoreleaseReturnValue(), и несколько других, если это было бы полезно для вас. Написанный таким образом, компилятор может использовать оптимизацию хвостового вызова для устранения ненужных шагов.

Таким образом, короткий ответ заключается в том, что ARC не использует тот же [удержание]/[выпуск ], которые мы использовали бы в более старых версиях Objecive C, поэтому, увидев, что код ARC-preprocessed не обязательно проинструктирует вас, как это сделать самостоятельно.

ARC не является необычным в реализации как шаг предварительной обработки в компиляторе - я считаю, что многие функции Objective C реализованы таким образом.

0

Нет, вы не можете вдаваться в такие детали, не вдаваясь в детали уровня сборки LLVM.