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
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 salida → Archivo de ensamblaje.
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.
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
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 –
posible duplicado de [Ver donde ARC está insertando retener y liberar] (http://stackoverflow.com/questions/8812098/seeing-where-arc-is-inserting-retain-and-releases) –