从编译指令中删除VS2015 stloc.0和ldloc.0

时间:2015-09-23 08:07:40

标签: .net compiler-construction mono visual-studio-2015

我正在使用Mono.Cecil.dll来反编译VS 2015应用。 在反编译期间,我注意到有2条指令(stloc.0& ldloc.0)缺失。 当我反编译VS 2013应用程序时,这不会发生。

反编译器或Visual Studio 2015编译器是否有问题已更改?

更新

我使用ILDasm反编译了代码。以下是2015年和2013年在Initialize组件中可以找到的内容。问题仍然存在:

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

1 个答案:

答案 0 :(得分:0)

从我看到的情况来看,这不应该产生任何可观察到的差异 - 它可能只是Roslyn成为更聪明的编译器的结果。该值仍在虚拟堆栈上,可以在需要时使用。没有必要将它存储在(虚拟)本地。

VS2015编译器是全新的,从头开始构建,因此可能存在一些差异。

注意VS2013版本的.maxstack为3,而VS2015的版本为4 - 这就是原因。 VS2013的编译器只保存了一个堆栈插槽,而VS2015保存了一个本地插槽(以及一些指令)。

该值在代码中使用了两次,每个编译以不同的方式处理它:VS2013将值保存在本地,以便在需要时检索。 VS2015只是让值保持在堆栈上,就在它第一次使用之前,dup踩它。

从JIT编译中查看生成的x86程序集可能会很有趣 - 两者甚至可能生成相同的代码,因为大多数优化都发生在JIT级别,而不是C#编译本身。

修改

好的,让我们仔细看看VS2015代码中的虚拟堆栈(为简化起见,我简化了):

  • Form推送为RuntimeHandle,然后将其弹出并推送Type(== typeof(Form)
  • 弹出Type,推new ResourceManager(取Type参数)
  • 推送this,按new Label,同时弹出两者以将标签存储在字段this.label1
  • 当前筹码:只是ResourceManager
  • 再次推送this,然后使用它来致电Control.SuspendLayout(== this.SuspendLayout
  • dup堆栈上的最后一个值(ResourceManager实例)
  • 推送this,推送this.label1(弹出this),推送"label1"
  • 当前筹码: ResourceManagerResourceManagerthis.label1"label1"
  • 调用ApplyResources(需要三个参数,所以弹出最后三个参数)

毕竟,我们仍然在堆栈上有ResourceManager,而不使用任何本地。