gpt4 book ai didi

swift - 仅在条件编译 block 中设置可选,编译器是否从发布版本中完全删除语句?

转载 作者:行者123 更新时间:2023-12-04 02:43:03 25 4
gpt4 key购买 nike

例如:

struct L {
#if DEBUG
static let og:((String) -> Void)? = { print($0) }
#else
static let og:((String) -> Void)? = nil
#endif
}
L.og?("Howdy!")
print("Done.")

在此代码的发布版本中,Swift 编译器如何处理 L.og?("Howdy!") 行?它是否完全优化了线路?或者表达式 L.og 在运行时评估为 nil?我如何证明任一答案?

最佳答案

我想我终于回答了我自己的问题。这次修改完全取代了我之前的回答,因为我认为这是错误的。

简答

编译器优化不会删除 Release 构建中的 L.og?("Howdy!") 行。 og? 的解包仍然在运行时发生。

证明

定义“发布”

在一个典型的Xcode项目中,Release的优化是什么?在目标build设置中,它是 SWIFT_OPTIMIZATION_LEVEL = -O

方法

我在 2 个不同的程序上运行了 swiftc -emit-assembly -O

程序A:

struct L {
#if DEBUG
static let og:((String) -> Void)? = { print($0) }
#else
static let og:((String) -> Void)? = nil
#endif
}
L.og?("Howdy!")

程序 B:

struct L {
#if DEBUG
static let og:((String) -> Void)? = { print($0) }
#else
static let og:((String) -> Void)? = nil
#endif
}

在程序集输出中,A

中的 main
_main:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
pushq %r13
pushq %rax
.cfi_offset %r13, -24
cmpq $-1, _globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0(%rip)
jne LBB0_4
LBB0_1:
movq _$s4main1LV2ogySScSgvpZ(%rip), %rax
testq %rax, %rax
je LBB0_3
movq _$s4main1LV2ogySScSgvpZ+8(%rip), %r13
movabsq $36805260308296, %rdi
movabsq $-1873497444986126336, %rsi
callq *%rax
LBB0_3:
xorl %eax, %eax
addq $8, %rsp
popq %r13
popq %rbp
retq
LBB0_4:
leaq _globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0(%rip), %rdi
leaq _globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0(%rip), %rsi
callq _swift_once
jmp LBB0_1
.cfi_endproc

.p2align 4, 0x90

B:

_main:
pushq %rbp
movq %rsp, %rbp
xorl %eax, %eax
popq %rbp
retq

.p2align 4, 0x90

如果编译器优化掉整行 L.og?("Howdy!"),那么我希望 main 来自 B将与 A 相同。它不是。因此,编译器将其保留。

非可选结果

对于非可选的空闭包,发现了类似的结果。对 L.og("Howdy!") 的调用保留在优化的程序集中,即使调用的是一个空函数。

即:

struct L {
#if DEBUG
static let og:((String) -> Void) = { print($0) }
#else
static let og:((String) -> Void) = { _ in }
#endif
}
L.og("Howdy!")

这是优化的 main 程序集:

_main:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
pushq %r13
pushq %rax
.cfi_offset %r13, -24
cmpq $-1, _globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0(%rip)
jne LBB0_1
LBB0_2:
movq _$s4main1LV2ogyySScvpZ+8(%rip), %r13
movabsq $36805260308296, %rdi
movabsq $-1873497444986126336, %rsi
callq *_$s4main1LV2ogyySScvpZ(%rip)
xorl %eax, %eax
addq $8, %rsp
popq %r13
popq %rbp
retq
LBB0_1:
leaq _globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0(%rip), %rdi
leaq _globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0(%rip), %rsi
callq _swift_once
jmp LBB0_2
.cfi_endproc

.p2align 4, 0x90

关于swift - 仅在条件编译 block 中设置可选,编译器是否从发布版本中完全删除语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58454708/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com