2012-05-03 19 views
14

Ho letto il Transitioning to ARC Release Notes nella sezione "Sommario". Hanno detto:È possibile vedere il codice generato da ARC in fase di compilazione?

ARC funziona aggiungendo il codice in fase di compilazione per garantire che gli oggetti rimangano in funzione finché necessario, ma non più. Concettualmente, segue le stesse convenzioni di gestione della memoria come conteggio dei riferimenti manuali (descritto nella Guida alla programmazione della memoria avanzata) aggiungendo le chiamate di gestione della memoria appropriate per .

Affinché il compilatore di generare codice corretto

Mi chiedo cosa risultato che ARC corretto il nostro codice.

La mia domanda: Possiamo vedere il cambiamento? (nel termine di alloc, mantengono, assegnare o rilasciare .Non livello di assieme!)

Motivo: Perché penso che sia buona per vedere il codice di best practice nella vecchia tradizione senza sviluppo modalità ARC.

+1

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

+0

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 –

+0

possibile duplicato di [Vedere dove ARC sta inserendo conservare e rilasciare] (http://stackoverflow.com/questions/8812098/seeing-where-arc-is-inserting-retain-and-releases) –

risposta

25

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

  1. 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 uscitaFile di assemblaggio.

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

+0

Sembra che tu abbia detto. Come pensi di emettere il codice a barre LLVM a livello di assembly, compilare velocemente? – Sakares

+0

@Jojas: Scusa non capisco cosa intendi con ", veloce compilazione?". – kennytm

+0

Vorrei chiedere la tua opinione, se ARC emette il codice a barre LLVM come hai detto. È fatto per lo scopo che impiega meno tempo nel processo di compilazione? (codice ObjC meno complesso, meno file di intestazione?) – Sakares

2

Mike Ash ha una discussione molto illuminante di implementazione ARC qui: http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

Si discute a livello di inserimento di chiamate di funzione C (objc_retain(), objc_release(), objc_retainAutoreleaseReturnValue(), e pochi altri, Se ciò è utile per te. Scritto in questo modo, il compilatore può utilizzare ottimizzazioni tail-call per eliminare i passaggi non necessari

La risposta breve, quindi, è che ARC non utilizza lo stesso [retain]/[release ] metodi che avremmo usato nelle versioni precedenti di Objecive C, quindi, vedendo il codice elaborato da ARC, non ti darebbe necessariamente istruzioni su come farlo da solo.

ARC non è insolito nell'essere implementato come un passo di pre-elaborazione nel compilatore - credo che molte caratteristiche dell'obiettivo C siano implementate in questo modo.

0

No, non è possibile entrare in tali dettagli senza entrare nei dettagli del livello di assemblaggio di LLVM.

Problemi correlati