从编译指令中删除VS2015 stloc.0和ldloc.0 [英] VS2015 stloc.0 and ldloc.0 are removed from compilation instructions
问题描述
我使用Mono.Cecil.dll反编译一个VS 2015应用程序。
在反编译过程中,我注意到有两条指令(stloc.0& ldloc.0)缺失。
当我反编译一个VS 2013应用程序时没有发生。
I am using Mono.Cecil.dll to decompile a VS 2015 app. During decompilation I noticed that there are 2 instructions (stloc.0 & ldloc.0) that are missing. This did not happen when I decompiled a VS 2013 application.
反编译器或Visual Studio 2015编译器有问题吗?
Is there a problem with the decompiler or Visual Studio 2015 complier has changed?
更新:
我已使用ILDasm反编译代码。这里是在2015年和2013年在初始化组件中找到的。问题仍然出现:
I have decompiled the code using ILDasm. Here is what can be found in 2015 and 2013 in Initialize component. The problem still appears:
2015
.method private hidebysig instance void InitializeComponent() cil managed
{
// Code size 125 (0x7d)
.maxstack 4
IL_0000: ldtoken VS2015DotNet4test.Form1
IL_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000a: newobj instance void [System]System.ComponentModel.ComponentResourceManager::.ctor(class [mscorlib]System.Type)
IL_000f: ldarg.0
IL_0010: newobj instance void [System.Windows.Forms]System.Windows.Forms.Label::.ctor()
IL_0015: stfld class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
IL_001a: ldarg.0
IL_001b: call instance void [System.Windows.Forms]System.Windows.Forms.Control::SuspendLayout()
IL_0020: dup
IL_0021: ldarg.0
IL_0022: ldfld class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
IL_0027: ldstr "label1"
IL_002c: callvirt instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
string)
IL_0031: ldarg.0
IL_0032: ldfld class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
IL_0037: ldstr "label1"
IL_003c: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
IL_0041: ldarg.0
IL_0042: ldstr "$this"
IL_0047: callvirt instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
string)
IL_004c: ldarg.0
IL_004d: ldc.i4.1
IL_004e: call instance void [System.Windows.Forms]System.Windows.Forms.ContainerControl::set_AutoScaleMode(valuetype [System.Windows.Forms]System.Windows.Forms.AutoScaleMode)
IL_0053: ldarg.0
IL_0054: call instance class [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection [System.Windows.Forms]System.Windows.Forms.Control::get_Controls()
IL_0059: ldarg.0
IL_005a: ldfld class [System.Windows.Forms]System.Windows.Forms.Label VS2015DotNet4test.Form1::label1
IL_005f: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection::Add(class [System.Windows.Forms]System.Windows.Forms.Control)
IL_0064: ldarg.0
IL_0065: ldstr "Form1"
IL_006a: call instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
IL_006f: ldarg.0
IL_0070: ldc.i4.0
IL_0071: call instance void [System.Windows.Forms]System.Windows.Forms.Control::ResumeLayout(bool)
IL_0076: ldarg.0
IL_0077: call instance void [System.Windows.Forms]System.Windows.Forms.Control::PerformLayout()
IL_007c: ret
} // end of method Form1::InitializeComponent
2013
.method private hidebysig instance void InitializeComponent() cil managed
{
// Code size 127 (0x7f)
.maxstack 3
.locals init (class [System]System.ComponentModel.ComponentResourceManager V_0)
IL_0000: ldtoken VS2013DotNet4test.Form1
IL_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000a: newobj instance void [System]System.ComponentModel.ComponentResourceManager::.ctor(class [mscorlib]System.Type)
IL_000f: stloc.0
IL_0010: ldarg.0
IL_0011: newobj instance void [System.Windows.Forms]System.Windows.Forms.Label::.ctor()
IL_0016: stfld class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
IL_001b: ldarg.0
IL_001c: call instance void [System.Windows.Forms]System.Windows.Forms.Control::SuspendLayout()
IL_0021: ldloc.0
IL_0022: ldarg.0
IL_0023: ldfld class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
IL_0028: ldstr "label1"
IL_002d: callvirt instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
string)
IL_0032: ldarg.0
IL_0033: ldfld class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
IL_0038: ldstr "label1"
IL_003d: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
IL_0042: ldloc.0
IL_0043: ldarg.0
IL_0044: ldstr "$this"
IL_0049: callvirt instance void [System]System.ComponentModel.ComponentResourceManager::ApplyResources(object,
string)
IL_004e: ldarg.0
IL_004f: ldc.i4.1
IL_0050: call instance void [System.Windows.Forms]System.Windows.Forms.ContainerControl::set_AutoScaleMode(valuetype [System.Windows.Forms]System.Windows.Forms.AutoScaleMode)
IL_0055: ldarg.0
IL_0056: call instance class [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection [System.Windows.Forms]System.Windows.Forms.Control::get_Controls()
IL_005b: ldarg.0
IL_005c: ldfld class [System.Windows.Forms]System.Windows.Forms.Label VS2013DotNet4test.Form1::label1
IL_0061: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection::Add(class [System.Windows.Forms]System.Windows.Forms.Control)
IL_0066: ldarg.0
IL_0067: ldstr "Form1"
IL_006c: call instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)
IL_0071: ldarg.0
IL_0072: ldc.i4.0
IL_0073: call instance void [System.Windows.Forms]System.Windows.Forms.Control::ResumeLayout(bool)
IL_0078: ldarg.0
IL_0079: call instance void [System.Windows.Forms]System.Windows.Forms.Control::PerformLayout()
IL_007e: ret
} // end of method Form1::InitializeComponent
推荐答案
从我看来,这不应该产生任何可观察到的差异 - 这可能只是Roslyn是一个更聪明的编译器的结果。该值仍然在虚拟堆栈上,准备在需要时使用。没有必要将它存储在(虚拟)本地。
From what I see, this shouldn't make any observable difference - it's likely simply the result of Roslyn being a smarter compiler. The value is still on the virtual stack, ready to be used when needed. There's no need to store it in a (virtual) local.
VS2015编译器是全新的,从头开始构建,因此可以预期一些差异。
The VS2015 compiler is completely new, built from scratch, so some differences are to be expected.
请注意VS2013版本的 .maxstack
为3,与VS2015中的4相比 - 这是原因。 VS2013的编译器只保存了一个堆栈槽,而VS2015保存了一个本地槽(和一些指令)。
Note how the VS2013 version has .maxstack
of 3, compared to 4 in VS2015 - this is the reason. VS2013's compiler simply saved one stack slot, while VS2015 saved one local slot (and a few instructions).
这个值在代码中使用了两次,与以不同的方式:VS2013保存在本地的值,需要时检索。 VS2015只是让值留在堆栈上,并且在它第一次使用之前, dup
ped。
The value is used twice in the code, each of the compilations dealing with that in a different way: VS2013 saved the value in a local, to be retrieved when needed. VS2015 simply let the value stay on stack, and just before it's used for the first time, dup
ped it.
从JIT编译中查看生成的x86程序集 - 这两个程序甚至可能产生相同的代码,这是很有趣的,因为大多数优化发生在JIT级别,而不是C#编译本身。
It might be interesting to have a look at the resulting x86 assembly from the JIT compilation - the two might even produce identical code, since most of the optimizations happen on the JIT level, not the C# compilation itself.
编辑:
好吧,让我们仔细看看VS2015代码中的虚拟堆栈
Okay, let's have a closer look at the virtual stack in the VS2015 code (I'm simplifying for clarity):
- 推荐
表单
为RuntimeHandle
,弹出并按类型
(==typeof(Form)
) - 弹出
键入
,推动new ResourceManager
$ c> Type 参数 - 按
/ code>,弹出以将标签存储在字段
this.label1
- / strong>只需
ResourceManager
- 再次按
此
Control.SuspendLayout
(==this.SuspendLayout
) -
dup
堆栈上的最后一个值(ResourceManager
实例) - c $ c> this ,push
this.label1
(弹出this
), code>label1 - 当前堆栈:
ResourceManager
,ResourceManager
,this.label1
,label1
/ li>
- 调用
ApplyResources
(它有三个参数,因此弹出最后三个)
- Push
Form
as aRuntimeHandle
, pop it and push theType
(==typeof(Form)
) - Pop
Type
, pushnew ResourceManager
(takes theType
argument) - Push
this
, pushnew Label
, pop both to store the label in the fieldthis.label1
- Current stack: just the
ResourceManager
- Push
this
again, and use it to callControl.SuspendLayout
(==this.SuspendLayout
) dup
the last value on stack (theResourceManager
instance)- Push
this
, pushthis.label1
(poppingthis
), push"label1"
- Current stack:
ResourceManager
,ResourceManager
,this.label1
,"label1"
- Call
ApplyResources
(which takes three arguments, so pop the last three)
在这之后,我们仍然有 ResourceManager
在堆栈上,而不使用任何本地。
After all this, we still have the ResourceManager
on stack, without using any local.
这篇关于从编译指令中删除VS2015 stloc.0和ldloc.0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!