Лишние NOPs и ветви в неоптимизированном MSIL
Когда я компилирую следующий код в качестве отладки...
public class MyClass
{
private int myField;
public int MyProperty
{
get { return myField; }
set { myField = value; }
}
}
... странный байт-код с кажущимися бесполезными инструкциями генерируется компилятором. Например, посмотрите, что генерируется для получателя свойства MyProperty
(разобран с ildasm.exe
):
.method public hidebysig specialname instance int32
get_MyProperty() cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init ([0] int32 CS$1$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 MSILTest.MyClass::myField
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method MyClass::get_MyProperty
В частности, что такое nop
в IL_0000
там делаешь? И почему компилятор генерирует это бесполезно br.s
инструкция в IL_0008
буквально из ниоткуда? Почему это создает временную локальную переменную CS$1$0000
?
Для конфигурации релиза набор инструкций генерируется, как ожидается:
IL_0000: ldarg.0
IL_0001: ldfld int32 MSILTest.MyClass::myField
IL_0006: ret
РЕДАКТИРОВАТЬ
Я думаю, что нашел ответ на вопрос, почему ветвь и временная локальная переменная находятся в другом вопросе: вероятно, это легко для установки точек останова во время отладки. Таким образом, остается вопрос: почему nop
Инструкция генерируется.
1 ответ
Компилятор создает эти коды операций, чтобы обеспечить лучший опыт отладки. В начале каждой строки C# компилятор вводит nop
поэтому отладчик может сломаться там. Ветвь и временная локальная переменная создаются для анализа возвращаемого значения функции.