未优化的 MSIL 中多余的 NOP 和分支 [重复]
Posted
技术标签:
【中文标题】未优化的 MSIL 中多余的 NOP 和分支 [重复]【英文标题】:Superfluous NOPs and branches in unoptimized MSIL [duplicate] 【发布时间】:2016-04-18 07:58:31 【问题描述】:当我将以下代码编译为调试时...
public class MyClass
private int myField;
public int MyProperty
get return myField;
set myField = value;
...编译器生成带有看似无用指令的奇怪字节码。比如看看属性MyProperty
的getter生成了什么(用ildasm.exe
反汇编):
.method public hidebysig specialname instance int32
get_MyProperty() cil managed
// Code size 12 (0xc)
.maxstack 1
.locals init ([0] int32 CS$1$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 MSILTest.MyClass::myField
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
// end of method MyClass::get_MyProperty
具体来说,nop
IL_0000
在那里做什么?为什么编译器会在IL_0008
处生成这条无用的br.s
指令?为什么会创建临时局部变量CS$1$0000
?
对于发布配置,指令集按预期生成:
IL_0000: ldarg.0
IL_0001: ldfld int32 MSILTest.MyClass::myField
IL_0006: ret
编辑
我想我已经找到了为什么分支和临时局部变量存在于different question 中的问题的答案:这可能是为了在调试期间轻松设置断点。所以剩下的问题是为什么会生成nop
指令。
【问题讨论】:
未优化的代码未优化。 NOP 是调试器断点的目标。删除由递归体面的解析器产生的冗余负载和存储需要一个窥孔优化器。消除不必要的本地人也是一项优化工作。 jitter 本身可以在没有编译器帮助的情况下处理这些优化工作。 另见Subtleties of C# IL codegen,谷歌第一次点击“C# debug nop”:“关闭优化后,C# 编译器会在所有地方发出 no-op IL 指令。带有调试信息打开和关闭优化,其中一些无操作将成为语句或表达式片段的断点目标,否则很难在其上放置断点“. 【参考方案1】:编译器创建这些操作码是为了提供更好的调试体验。在每个 c# 行的开头,编译器将引入
nop
所以调试器可以在那里中断。发出分支和临时局部变量,让您分析函数的返回值。
【讨论】:
以上是关于未优化的 MSIL 中多余的 NOP 和分支 [重复]的主要内容,如果未能解决你的问题,请参考以下文章