是否可以在编译时查看ARC生成的代码? [英] Is it possible to see the code generated by ARC at compile time?

查看:95
本文介绍了是否可以在编译时查看ARC生成的代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读过渡到ARC发行说明在摘要"部分.他们告诉:

ARC的工作原理是在编译时添加代码,以确保对象处于活动状态 只要有必要,但不再.从概念上讲,它遵循相同的 内存管理约定作为手动引用计数(描述了 在高级内存管理编程指南中),方法是添加 适当的内存管理会为您服务.

为了使编译器生成正确的代码

我想知道ARC更正我们的代码有什么结果.

我的问题:我们可以看到更改吗? (用alloc,retain,assign或release来表示.不是汇编级别!)

原因:因为我认为在不使用ARC模式的旧传统开发中最好的实践代码是很好的.

解决方案

clang中的ARC无法通过将代码从ObjC重写到ObjC来工作,但是会在代码生成过程中发出额外的保留/释放LLVM位代码.这意味着,如果不进入LLVM IR/程序集级别,就不可能知道编译器是如何修复"它的.


如果ARC发出了您所说的LLVM位代码.是否出于在编译过程中使用较少时间的目的? (较少复杂的ObjC代码,较少头文件?)

如果编译器可以减少遍历代码的次数,那总会更好.


您能告诉我一些示例或实用程序来显示汇编级别的代码吗?

要获取汇编代码,您可以

  1. 直接从编译器生成程序集.在命令行中,调用编译器时添加-S标志.结果是一个.S文件,其中包含汇编代码.在Xcode项目中,打开源代码文件,然后转到产品(在菜单栏上)→生成输出汇编文件. p>

  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在代码生成过程中插入的内容.通过手工反编译,我们将得到:

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 的链接所描述的相同.

I have read the Transitioning to ARC Release Notes in "Summary" Section. They told :

ARC works by adding code at compile time to ensure that objects live as long as necessary, but no longer. Conceptually, it follows the same memory management conventions as manual reference counting (described in Advanced Memory Management Programming Guide) by adding the appropriate memory management calls for you.

In order for the compiler to generate correct code

I wonder what result that ARC corrected our code.

My question : Can we see the change? (In the term of alloc , retain , assign or release .Not assembly level !)

Reason : Because I think It's good to see the best-practice code in the old tradition development without ARC mode.

解决方案

ARC in clang doesn't work by rewriting code from ObjC to ObjC, but emitting the extra retain/release LLVM bitcode during code-gen. That means, it is not possible to know how the compiler "fix" it without going to LLVM IR / assembly level.


If ARC emit the LLVM bitcode as you said. Is it made for the purpose that use less time in compile process? (less complex ObjC code, less header file?)

It is always better if the compiler can reduce the number of passes through the code.


Can you show me some example or utility that show the code in assembly level?

To get the assembly code, you could either

  1. Generate assembly directly from the compiler. In the command line, add the -S flag when invoking the compiler. The result is a .S file containing the assembly code. In an Xcode project, open the source code file, then go to Product (on menu bar) → Generate OutputAssembly File.

  2. Generate the object file, and then disassemble it. The built-in command otool -tvV <file> can perform disassembly, and there are advanced tools like otx (free) or IDA (free for evaluation).

I prefer route 2 because it generates less garbage and the disassembly tool can be configured to produce more useful information. Anyway, with either method you need to be able to read assembly code.

Take this code as example:

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

After compiling the following assembly will be produced (analyzed using 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}

Without going into detail, you can see there are many _objc_release and _objc_retainAutoreleasedReturnValue. These are what ARC inserts during code-gen. Decompiling it by hand, we'll get:

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;

which is just the same as what @c roald's link describes.

这篇关于是否可以在编译时查看ARC生成的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆