是否有可能看到在编译时通过电弧产生的代码?(Is it possible to see the co

2019-06-24 03:27发布

我已阅读过渡到ARC发行说明中的“摘要”部分。 他们告诉:

ARC的工作原理是在编译时添加代码,以确保对象的生活,只要有必要,但不再。 从概念上讲,它加入了对你合适的内存管理调用遵循相同的内存管理公约手动引用计数(高级内存管理编程指南中所述)。

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

我不知道结果是ARC纠正了我们的代码。

我的问题:我们可以看到改变? (在ALLOC期限,保留,转让或释放。不装配水平!)

原因:因为我觉得这是很好的看到老传统发展的最佳实践代码而不ARC模式。

Answer 1:

ARC在铛不从ObjC重写代码ObjC,但在发射代码生成额外的保留/释放LLVM位码工作。 这意味着,这是不可能知道如何编译器“修复”,它没有去LLVM IR /装配水平。


如果ARC发出LLVM位码如你所说。 它是用于在编译过程中使用更少的时间而作出的? (不太复杂ObjC代码,少头文件?)

它始终是更好,如果编译器可以通过降低代码的遍数。


你能告诉我,显示汇编级代码中的一些例子或效用?

为了得到汇编代码,您既可以

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

  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罗尔德的链接描述。



Answer 2:

迈克水曲柳具有ARC实施的一个很有启发的讨论在这里: http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

他讨论了它在插入C函数的水平调用(objc_retain(),objc_release(),objc_retainAutoreleaseReturnValue(),和其他几个人,如果这将是对你有所帮助。写这样一来,编译器可以使用尾部调用优化,以消除不必要的步骤。

简短的回答,因此,是ARC不使用相同的[保留]我们将在旧版本Objecive的C使用了/ [发布]的方法,等于是看到了ARC-预处理代码不一定会教你如何自己做。

ARC是不是在被实现为编译器预处理步骤不寻常的 - 我相信目标C的许多功能都是以这种方式实现。



Answer 3:

不,你不能进入这些细节而不进入LLVM的装配水平的细节。



文章来源: Is it possible to see the code generated by ARC at compile time?