.NET IL .maxstack指令如何工作?

问题描述:

我想知道.maxstack是如何工作的。我知道它并不是与你声明的类型的实际大小有关,而是与它们的数量有关。我的问题是:.NET IL .maxstack指令如何工作?

  1. 这是否适用于只是为了 功能,或所有我们所要求的功能 ?
  2. 即使它只是为功能 分别是.maxstack正在申报, 你怎么知道什么是maxstack如果 你有分支?你去看看 所有的“路径”,并返回 可能的最大值?
  3. 如果将其设置为16, 实际上有17个变量会发生什么?
  4. 如果我将 设置为256,会有太大的惩罚吗?

.maxstack是IL验证的一部分。基本上.maxstack告诉JIT它需要为该方法保留的最大堆栈大小。例如,x = y + (a - b)转化为

(伪IL :)

1. Push y on the stack 
2. Push a on the stack 
3. Push b on the stack 
4. Pop the last two items from the stack, 
     substract them and 
     push the result on the stack 
5. Pop the last two items from the stack, 
     add them and 
     push the result on the stack 
6. Store the last item on the stack in x and 
     pop the last item from the stack 

正如你所看到的,有在堆栈中的每个时间上最多3项。 如果您为此方法将.maxstack设置为2(或更少),则代码将不会运行。

而且,你不能有这样的事情,因为这将需要一个无限的堆栈大小:

1. Push x on the stack 
2. Jump to step 1 

回答您的问题:

  1. 只是为了功能
  2. 你去看看所有路径并返回可能的最大值
  3. 它与变量的数量无关,请参阅Lasse V. Karlsen的回答
  4. 看起来不是一个好主意,但我不知道。

你真的要自己计算一下.maxstack吗? System.Reflection.Emit为你计算IIRC。

+0

我还挺做,虽然我会让它保持原样。我只是从其他可执行文件编辑一些IL代码,但我插入的方法只有2个参数,所以我认为它永远不会干扰IL方法中已经存在的.maxstack。 – 2009-08-09 06:10:01

它无关的声明的变量的,而是一切都与你需要多少价值,以便计算一些表达推栈在任何给定的时间。

例如,在下面的表达式,我会假设2个值需要被压入堆栈:

x = y + z; 

这是无关的事实,即至少有3个变量目前,X,Y ,和z,也可能是其他。

不幸的是,我不知道你的其他问题的答案,我猜测实验将是找到一些答案的方法之一。

+0

啊。因此,如果我的表达式从来没有超过8个操作数,并且我从我的方法调用的任何函数都不会超过8个参数,那么我将永远不会超过.maxstack 8? – 2009-08-06 21:00:10

+0

即使两个操作符只有2个操作数,'x = y +(a - b)'也需要3的堆栈大小。 – dtb 2009-08-07 08:15:24

您可以参考以下内容,ECMA标准,以获得更好的理解:

void msd(string a, 
    string b, 
    string c, 
    string d, 
    string e) 
    { 
    Console.WriteLine(a); 
} 

msd("a","b","c","d","e"); 

当我运行ildasm.exe我得到这个:

{ 
    .entrypoint 
    // Code size  40 (0x28) 
    .maxstack 8 
    IL_0000: nop 
    IL_0001: nop 
    IL_0002: ldstr  "a" 
    IL_0007: ldstr  "b" 
    IL_000c: ldstr  "c" 
    IL_0011: ldstr  "d" 
    IL_0016: ldstr  "e" 
    IL_001b: call  void sf.Program::'<Main>g__msd|0_0'(string, 
                  string, 
                  string, 
                  string, 
                  string) 
    IL_0020: nop 
    IL_0021: call  string [mscorlib]System.Console::ReadLine() 
    IL_0026: pop 
    IL_0027: ret 
} // end of method Program::Main 

从上面。我发现最大的stakc值不是由推动&弹出式指令决定的。

我不知道真正的堆栈数值是什么。所以,我参考ildasm反汇编代码来确定真正的最大堆栈值。