gpt4 book ai didi

f# - F# 代码发布版本中的 NOP

转载 作者:行者123 更新时间:2023-12-01 16:31:48 27 4
gpt4 key购买 nike

我正在 VS2010 beta2 中使用 F#,由于我是 F# 新手,我只是选择了一个常见示例,然后继续实现阶乘函数,如下所示:

let rec factorial n =
if n <= 1 then 1 else n * factorial (n - 1);;

如果我构建它并在 Reflector 中查看生成的代码,我会得到相应的 C# 代码:

public static int Factorial(int n) {
if (n <= 1)
return 1;

return n * Factorial(n - 1);
}

因此,如果我编译 F# 代码的 Reflector 的 C# 表示形式,我希望获得相同的 IL。

但是,如果我在 Release模式下编译这两个片段并比较生成的 IL,它们是不同的(它们在功能上相同,但仍然有点不同)。

C# 实现编译为:

.method public hidebysig static int32 Factorial(int32 n) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldc.i4.1
L_0002: bgt.s L_0006
L_0004: ldc.i4.1
L_0005: ret
L_0006: ldarg.0
L_0007: ldarg.0
L_0008: ldc.i4.1
L_0009: sub
L_000a: call int32 TestApp.Program::Factorial(int32)
L_000f: mul
L_0010: ret
}

F# 实现编译为:

.method public static int32 factorial(int32 n) cil managed
{
.maxstack 5 <=== Different maxstack
L_0000: nop <=== nop instruction?
L_0001: ldarg.0
L_0002: ldc.i4.1
L_0003: bgt.s L_0007
L_0005: ldc.i4.1
L_0006: ret
L_0007: ldarg.0
L_0008: ldarg.0
L_0009: ldc.i4.1
L_000a: sub
L_000b: call int32 FSharpModule::factorial(int32)
L_0010: mul
L_0011: ret
}

除了 maxstack 不同以及 F# 方法中附加的 NOP 指令之外,生成的代码是相同的。

这可能并不重要,但我很好奇为什么 F# 编译器会在发布版本中插入 NOP。

谁能解释一下为什么吗?

(我完全清楚 F# 编译器没有经过与 C# 编译器相同级别的实际测试,但这非常明显,我认为它会被捕获)。

编辑:编译命令如下

C:\Program Files\Microsoft F#\v4.0\fsc.exe -o:obj\Release\FSharpLib.dll 
--debug:pdbonly --noframework --define:TRACE --optimize+
--target:library --warn:3 --warnaserror:76 --vserrors --utf8output --fullpaths
--flaterrors "C:\Temp\.NETFramework,Version=v4.0.AssemblyAttributes.fs" Module1.fs

(为简洁起见,删除了引用的程序集)。

最佳答案

maxstack 的差异是由于 C# 编译器使用“light”方法体 header 编译第一个方法,只要代码很小、没有异常且没有本地变量,就会使用该方法体 header 。在这种情况下,未指定 maxstack,默认为 8。

F# 编译器使用“fat”方法体 header ,并指定它计算出的 maxstack。

至于nop,那是因为你是在 Debug模式下编译的。他们总是以 nop 开始方法体。请参阅 fsharp/ilxgen.ml:

// Add a nop to make way for the first sequence point. There is always such a 
// sequence point even when zapFirstSeqPointToStart=false
do if mgbuf.cenv.generateDebugSymbols then codebuf.Add(i_nop);

如果我在没有调试符号的情况下编译你的阶乘,我不会得到 nop。

关于f# - F# 代码发布版本中的 NOP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1612543/

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