2012-05-03 6 views
14

He leído Transitioning to ARC Release Notes en la sección "Resumen". Ellos dijeron:¿Es posible ver el código generado por ARC en tiempo de compilación?

ARC trabaja agregando código en tiempo de compilación para asegurar que los objetos vivan el tiempo que sea necesario, pero no más. Conceptualmente, sigue las mismas convenciones de administración de memoria que el recuento manual de referencias (descrito en la Guía de programación avanzada de administración de memoria) al agregar las llamadas de administración de memoria apropiadas .

Para que el compilador para generar código correcto

Me pregunto lo que el resultado ARC corregido nuestro código.

Mi pregunta es: ¿Podemos ver el cambio? (En el término de alloc, retener, asignar o liberar .Not nivel de ensamblado!)

Motivo: porque creo que es bueno para ver el código de buenas prácticas en la antigua tradición de desarrollo sin el modo de ARC.

+1

Para el caso de estudio, me refiero al "viejo desarrollo de la tradición" sobre cómo podríamos asignarlo, retenerlo, asignarlo o liberarlo correctamente. Tampoco me gustaría programar el código en detalle de ensamblaje :-). – Sakares

+0

Puede leer la documentación vinculada desde el artículo que cita, ARC simplemente hace lo mismo que se describe en este artículo. Lea la sección "Política de administración de memoria" para comenzar, la mayoría de las reglas de ARC para la programación diaria se derivan de allí. https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html –

+0

posible duplicado de [Ver donde ARC está insertando retener y liberar] (http://stackoverflow.com/questions/8812098/seeing-where-arc-is-inserting-retain-and-releases) –

Respuesta

25

ARC en clang no funciona reescribiendo el código de ObjC a ObjC, pero emitiendo el código de bit LLVM retención/liberación adicional durante code-gen. Eso significa que no es posible saber cómo el compilador lo "arregla" sin pasar al nivel de ensamblaje/IR de LLVM.


Si ARC emiten el código binario LLVM como usted ha dicho. ¿Está hecho para el propósito de usar menos tiempo en el proceso de compilación? (código de ObjC menos complejo, menos archivo de encabezado?)

Siempre es mejor si el compilador puede reducir el número de pasadas a través del código.


¿Me puede mostrar algún ejemplo o utilidad que muestran el código de nivel de ensamblado?

Para obtener el código de montaje, se puede ya sea

  1. Generar montaje directamente del compilador. En la línea de comando, agregue el indicador -S al invocar el compilador. El resultado es un archivo .S que contiene el código de ensamblaje. En un proyecto de Xcode, abra el archivo de código fuente, luego vaya a Producto (en la barra de menú) → Generar salidaArchivo de ensamblaje.

  2. Genere el archivo de objeto, y luego desmóntelo. El comando incorporado otool -tvV <file> puede realizar el desmontaje, y existen herramientas avanzadas como otx (gratis) o IDA (gratis para evaluación).

Prefiero la ruta 2 porque genera menos basura y la herramienta de desensamblaje se puede configurar para producir información más útil.De todos modos, con cualquiera de los métodos, debe poder leer el código de ensamblaje.

Tome este código como ejemplo:

- (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; 
} 

Después de compilar la siguiente asamblea será producido (analizados utilizando AIF):

 
-[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} 

Sin entrar en detalles, se puede ver que hay muchos _objc_release y _objc_retainAutoreleasedReturnValue. Esto es lo que ARC inserta durante code-gen. descompilación a mano, nos pondremos en contacto:

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; 

que es lo mismo que lo enlace @c roald 's describe.

+0

Parece ser como dijiste. ¿Cómo piensas en emitir código de bits LLVM en el nivel de ensamblaje, compilación rápida? – Sakares

+0

@Jojas: Lo siento, no entiendo lo que quieres decir con ", compilación rápida?". – kennytm

+0

Me gustaría preguntar su opinión, si ARC emite el código de bits LLVM como dijo. ¿Está hecho para el propósito de usar menos tiempo en el proceso de compilación? (código de ObjC menos complejo, menos archivo de cabecera?) – Sakares

2

Mike Ash tiene una discusión muy iluminadora de aplicación ARC aquí: http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

Se discute a nivel de la inserción de las llamadas a funciones C (objc_retain(), objc_release(), objc_retainAutoreleaseReturnValue(), y algunos otros, si eso fuera útil para usted. Escrito de esa manera, el compilador puede usar optimizaciones de cola para eliminar los pasos innecesarios.

La respuesta corta, por lo tanto, es que ARC no usa el mismo [retención]/[publicación ] métodos que hubiésemos usado en versiones anteriores de Objecive C, por lo que ver el código preprocesado de ARC no necesariamente le indicaría cómo hacerlo usted mismo.

No es inusual que ARC se implemente como un paso de preproceso en el compilador. Creo que muchas características del objetivo C se implementan de esta manera.

0

No, no puede entrar en esos detalles sin entrar en los detalles de nivel de ensamblaje de LLVM.

Cuestiones relacionadas