Подтвердить что ты не робот

Как работает директива .NET IL.maxstack?

Я хотел бы знать, как работает .maxstack. Я знаю, что это не связано с фактическим размером типов, которые вы объявляете, но с их количеством. Мои вопросы:

  • это применимо только для функции или ко всем функциям к которому мы призываем?
  • даже если он просто для функции были объявлены .maxstack, как узнать, что такое maxstack, если у вас есть ветвление? Вы идите и смотрите все "пути" и вернуть возможно максимальное значение?
  • Что произойдет, если я установил значение 16 и на самом деле существует 17 переменных?
  • Есть ли слишком большой штраф, если я установите его на 256?

Спасибо

4b9b3361

Ответ 1

.maxstack является частью проверки IL. В основном .maxstack указывает JIT максимальный размер стека, который он должен зарезервировать для этого метода. Например, x = y + (a - b) переводит на

(Pseudo 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

Чтобы ответить на ваши вопросы:

  • Только для функции
  • Вы просматриваете все пути и возвращаете максимальное возможное значение
  • Это не связано с количеством переменных, см. Lasse V. Karlsen answer
  • Не кажется хорошей идеей, но я не знаю.

Вам действительно нужно рассчитать .maxstack самостоятельно? System.Reflection.Emit рассчитывает его для вас IIRC.

Ответ 2

Это не имеет никакого отношения к числу объявленных переменных, но вместо этого все зависит от того, сколько значений вам нужно нажать на стек в любой момент времени, чтобы вычислить некоторое выражение.

Например, в следующем выражении я бы предположил, что 2 значения необходимо вставить в стек:

x = y + z;

Это не связано с тем, что имеется как минимум 3 переменных, x, y и z, а также, возможно, и другие.

К сожалению, я не знаю ответа на ваши другие вопросы, и я бы предположил, что эксперименты будут одним из способов найти ответы.

Ответ 3

Для лучшего понимания вы можете обратиться к следующему и стандарту 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

из приведенного выше. Я нашел значение max stakc, которое не определяется инструкциями push и pop.

Я не знал, каковы реальные значения номера стека. Итак, я ссылаюсь на код ildasm дизассемблирования, чтобы определить значение максимального максимального стека.