VS2015 stloc.0 和 ldloc.0 从编译指令中移除
VS2015 stloc.0 and ldloc.0 are removed from compilation instructions
我正在使用 Mono.Cecil.dll 反编译 VS 2015 应用程序。
在反编译过程中,我注意到缺少 2 条指令(stloc.0 和 ldloc.0)。
当我反编译 VS 2013 应用程序时,这并没有发生。
是反编译器有问题还是Visual Studio2015编译器变了?
更新:
我已经使用 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
据我所知,这应该不会造成任何可观察到的差异 - 这可能只是 Roslyn 是一个更智能的编译器的结果。该值仍在虚拟堆栈中,随时可以在需要时使用。无需将其存储在(虚拟)本地。
VS2015 编译器是全新的,从头开始构建,因此存在一些差异是可以预料的。
请注意 VS2013 版本的 .maxstack
为 3,而 VS2015 中为 4 - 这就是原因。 VS2013 的编译器只节省了一个堆栈槽,而 VS2015 节省了一个本地槽(和一些指令)。
该值在代码中使用了两次,每次编译都以不同的方式处理该值:VS2013 将该值保存在本地,以在需要时检索。 VS2015 只是让值保留在堆栈中,并且在第一次使用它之前,dup
ped 它。
查看 JIT 编译生成的 x86 程序集可能会很有趣 - 两者甚至可能生成相同的代码,因为大多数优化发生在 JIT 级别,而不是 C# 编译本身。
编辑:
好的,让我们仔细看看 VS2015 代码中的虚拟堆栈(为了清楚起见,我进行了简化):
- 将
Form
作为 RuntimeHandle
推入,将其弹出并推入 Type
(== typeof(Form)
)
- Pop
Type
, push new ResourceManager
(接受 Type
参数)
- 压入
this
、压入new Label
、弹出两者以将标签存储在字段this.label1
- 当前堆栈:只是
ResourceManager
- 再次按下
this
,并用它调用Control.SuspendLayout
(==this.SuspendLayout
)
dup
堆栈中的最后一个值(ResourceManager
实例)
- 推送
this
,推送this.label1
(弹出this
),推送"label1"
- 当前堆栈:
ResourceManager
, ResourceManager
, this.label1
, "label1"
- 调用
ApplyResources
(需要三个参数,所以弹出最后三个)
在所有这一切之后,我们仍然有 ResourceManager
在堆栈上,没有使用任何本地。
我正在使用 Mono.Cecil.dll 反编译 VS 2015 应用程序。 在反编译过程中,我注意到缺少 2 条指令(stloc.0 和 ldloc.0)。 当我反编译 VS 2013 应用程序时,这并没有发生。
是反编译器有问题还是Visual Studio2015编译器变了?
更新:
我已经使用 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
据我所知,这应该不会造成任何可观察到的差异 - 这可能只是 Roslyn 是一个更智能的编译器的结果。该值仍在虚拟堆栈中,随时可以在需要时使用。无需将其存储在(虚拟)本地。
VS2015 编译器是全新的,从头开始构建,因此存在一些差异是可以预料的。
请注意 VS2013 版本的 .maxstack
为 3,而 VS2015 中为 4 - 这就是原因。 VS2013 的编译器只节省了一个堆栈槽,而 VS2015 节省了一个本地槽(和一些指令)。
该值在代码中使用了两次,每次编译都以不同的方式处理该值:VS2013 将该值保存在本地,以在需要时检索。 VS2015 只是让值保留在堆栈中,并且在第一次使用它之前,dup
ped 它。
查看 JIT 编译生成的 x86 程序集可能会很有趣 - 两者甚至可能生成相同的代码,因为大多数优化发生在 JIT 级别,而不是 C# 编译本身。
编辑:
好的,让我们仔细看看 VS2015 代码中的虚拟堆栈(为了清楚起见,我进行了简化):
- 将
Form
作为RuntimeHandle
推入,将其弹出并推入Type
(==typeof(Form)
) - Pop
Type
, pushnew ResourceManager
(接受Type
参数) - 压入
this
、压入new Label
、弹出两者以将标签存储在字段this.label1
- 当前堆栈:只是
ResourceManager
- 再次按下
this
,并用它调用Control.SuspendLayout
(==this.SuspendLayout
) dup
堆栈中的最后一个值(ResourceManager
实例)- 推送
this
,推送this.label1
(弹出this
),推送"label1"
- 当前堆栈:
ResourceManager
,ResourceManager
,this.label1
,"label1"
- 调用
ApplyResources
(需要三个参数,所以弹出最后三个)
在所有这一切之后,我们仍然有 ResourceManager
在堆栈上,没有使用任何本地。