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.
The VS2015 compiler is completely new, built from scratch, so some differences are to be expected.
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).
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.
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.
EDIT:
Okay, let's have a closer look at the virtual stack in the VS2015 code (I'm simplifying for clarity):
- Push
Form
as a RuntimeHandle
, pop it and push the Type
(== typeof(Form)
)
- Pop
Type
, push new ResourceManager
(takes the Type
argument)
- Push
this
, push new Label
, pop both to store the label in the field this.label1
- Current stack: just the
ResourceManager
- Push
this
again, and use it to call Control.SuspendLayout
(== this.SuspendLayout
)
dup
the last value on stack (the ResourceManager
instance)
- Push
this
, push this.label1
(popping this
), push "label1"
- Current stack:
ResourceManager
, ResourceManager
, this.label1
, "label1"
- Call
ApplyResources
(which takes three arguments, so pop the last three)
After all this, we still have the ResourceManager
on stack, without using any local.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…