ARC in clang non funziona riscrivendo il codice da ObjC a ObjC, ma emettendo il bitcode LLVM extra di mantenimento/rilascio durante il codice-gen. Ciò significa che non è possibile sapere in che modo il compilatore lo "aggiusta" senza passare a LLVM IR/livello di assemblaggio.
Se ARC emettono il codice binario che LLVM come hai detto. È fatto per lo scopo che impiega meno tempo nel processo di compilazione? (Meno complesso codice objC, meno file di intestazione?)
E 'sempre meglio se il compilatore in grado di ridurre il numero di passaggi attraverso il codice.
Mi potete mostrare qualche esempio o l'utilità che mostrano il codice a livello di assieme?
per ottenere il codice assembly, si potrebbe o
Genera assembly direttamente dal compilatore. Nella riga di comando, aggiungi il flag -S
durante il richiamo del compilatore. Il risultato è un file .S
contenente il codice assembly. In un progetto Xcode, aprire il file del codice sorgente, quindi passare a Prodotto (nella barra dei menu) → Genera uscita → File di assemblaggio.
Generare il file oggetto e quindi disassemblarlo. Il comando integrato otool -tvV <file>
può eseguire lo smontaggio e sono disponibili strumenti avanzati come otx (gratuito) o IDA (gratuito per la valutazione).
preferisco percorso 2 perché genera meno rifiuti e lo strumento di smontaggio può essere configurato per produrre informazioni più utili.Ad ogni modo, con entrambi i metodi è necessario essere in grado di leggere il codice assembly.
Prendete questo codice come ad esempio:
- (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;
}
Dopo aver compilato il seguente assemblea sarà prodotto (analizzati utilizzando 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}
Senza entrare nei dettagli, si può vedere ci sono molti _objc_release
e _objc_retainAutoreleasedReturnValue
. Questi sono gli inserimenti ARC durante il codice-gen. decompilazione a mano, ci arriveremo:
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;
che è proprio lo stesso di quello collegamento @c roald s' descrive.
Per il caso di studio, intendo lo "sviluppo di una vecchia tradizione" riguarda il modo in cui possiamo allocarli, conservarli, assegnarli o rilasciarli correttamente. Inoltre, non mi piacerebbe scrivere codice nel dettaglio dell'assieme :-). – Sakares
Puoi solo leggere la documentazione collegata all'articolo che citi, ARC fa esattamente la stessa cosa descritta in questo articolo. Leggi la sezione "Politica di gestione della memoria" per iniziare, la maggior parte delle regole ARC per la programmazione giornaliera derivano da lì. https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html –
possibile duplicato di [Vedere dove ARC sta inserendo conservare e rilasciare] (http://stackoverflow.com/questions/8812098/seeing-where-arc-is-inserting-retain-and-releases) –