Swift编译器是否优化了空闭包?

Jos*_*own 6 swift

我很想知道Swift 1.2编译器是否优化了空闭包.以下两个陈述是否相同?

1:

self.presentViewController(alertController, animated: true) {}
Run Code Online (Sandbox Code Playgroud)

2:

self.presentViewController(alertController, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)

谢谢!

Ral*_*nso 5

正如@rickster建议的那样,我看一下这个文件生成的x86程序集(simple.swift):

func thingWithClosure(a: Int, b: (() -> Void)?) {
    println(a)
    b?()
}


thingWithClosure(3) {
    println("i'm a closure")
}

thingWithClosure(5, nil)

thingWithClosure(2) {}
Run Code Online (Sandbox Code Playgroud)

我的装配非常生疏,但我可以稍微眯一下......

未优化生成的x86程序集的.main部分,或至少部分部分,如下所示:

    callq   _swift_once
    movq    __TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__@GOTPCREL(%rip), %rax
    movq    -64(%rbp), %rcx
    movq    %rcx, (%rax)
    leaq    l_metadata+16(%rip), %rdi
    movl    $32, %r9d
    movl    %r9d, %eax
    movl    $7, %r9d
    movl    %r9d, %edx
    movq    %rax, %rsi
    movq    %rdx, -80(%rbp)
    movq    %rax, -88(%rbp)
    callq   _swift_allocObject
    leaq    __TF6simpleU_FT_T_(%rip), %rcx
    movq    %rcx, 16(%rax)
    movq    $0, 24(%rax)
    leaq    __TPA__TTRXFo__dT__XFo_iT__iT__(%rip), %rcx
    movq    %rcx, -16(%rbp)
    movq    %rax, -8(%rbp)
    movq    -16(%rbp), %rsi
    movl    $3, %r9d
    movl    %r9d, %edi
    movq    %rax, %rdx
        --> callq   __TF6simple16thingWithClosureFTSiGSqFT_T___T_
    movq    $0, -24(%rbp)
    movq    $0, -32(%rbp)
    movl    $5, %r9d
    movl    %r9d, %edi
    movq    -72(%rbp), %rsi
    movq    -72(%rbp), %rdx
        --> callq   __TF6simple16thingWithClosureFTSiGSqFT_T___T_
    leaq    l_metadata2+16(%rip), %rdi
    movq    -88(%rbp), %rsi
    movq    -80(%rbp), %rdx
    callq   _swift_allocObject
    leaq    __TF6simpleU0_FT_T_(%rip), %rcx
    movq    %rcx, 16(%rax)
    movq    $0, 24(%rax)
    leaq    __TPA__TTRXFo__dT__XFo_iT__iT__3(%rip), %rcx
    movq    %rcx, -48(%rbp)
    movq    %rax, -40(%rbp)
    movq    -48(%rbp), %rsi
    movl    $2, %r9d
    movl    %r9d, %edi
    movq    %rax, %rdx
        --> callq   __TF6simple16thingWithClosureFTSiGSqFT_T___T_
    xorl    %eax, %eax
    addq    $96, %rsp
    popq    %rbp
    retq
    .cfi_endproc
Run Code Online (Sandbox Code Playgroud)

我已经指出了调用函数的位置-->.从每条callq指令查看一些指令,您可以看到a参数移入r9d寄存器的位置.

同样,优化输出:

    callq   _swift_once
    movq    __TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__@GOTPCREL(%rip), %rax
    movq    %r14, (%rax)
    movq    $3, -24(%rbp)
    movq    __TMdSi@GOTPCREL(%rip), %rbx
    addq    $8, %rbx
    leaq    -24(%rbp), %rdi
    movq    %rbx, %rsi
    callq   __TFSs7printlnU__FQ_T_
    leaq    L___unnamed_1(%rip), %rax
    movq    %rax, -48(%rbp)
    movq    $13, -40(%rbp)
    movq    $0, -32(%rbp)
    movq    __TMdSS@GOTPCREL(%rip), %rsi
    addq    $8, %rsi
    leaq    -48(%rbp), %rdi
        --> callq   __TFSs7printlnU__FQ_T_
    movq    $5, -56(%rbp)
    leaq    -56(%rbp), %rdi
    movq    %rbx, %rsi
        --> callq   __TFSs7printlnU__FQ_T_
    movq    $2, -64(%rbp)
    leaq    -64(%rbp), %rdi
    movq    %rbx, %rsi
        --> callq   __TFSs7printlnU__FQ_T_
    xorl    %eax, %eax
    addq    $48, %rsp
    popq    %rbx
    popq    %r14
    popq    %rbp
    retq
    .cfi_endproc
Run Code Online (Sandbox Code Playgroud)

这里,编译器已经内联了函数,所以我已经指出了println调用-->.

几年前我使用模拟的16位cpu介绍了x86程序集,所以我不会假装我确切地知道这里发生了什么,但在我看来,编译时-O,编译器会发出大致相同的代码(就指令数而言,但可能不是在内存查找等方面).似乎调用println是穿插leaq(加载有效地址)指令,所以我们可以跳到那里,但我不确定在哪里(可能是更多的指令?可能是加载静态数据?),或者如果它事项.

未经优化的版本会针对nil参数案例发出明显更多的指令,因此主要区别可能是调试性能.

当然,这是x86,所以它在ARM上可能完全不同......也许ARM组件,LLVM IR或Swift IR输出会带来更多光线?

如果有更好理解的人可以澄清,我很乐意更新这个答案.