Я думаю, что наблюдаю за компилятором .NET JIT, не вставляя или не оптимизируя вызовы на пустые статические методы, которые не имеют побочных эффектов, что несколько удивительно, учитывая некоторые бесплатные онлайн-ресурсы.
Моя среда - это Visual Studio 2013 на x64, Windows 8.1,.NET Framework 4.5.
Учитывая эту простую тестовую программу (https://ideone.com/2BRCpC)
class Program
{
static void EmptyBody()
{
}
static void Main()
{
EmptyBody();
}
}
Сборка с оптимизацией вышеуказанной программы создает следующий MSIL для Main
и EmptyBody
:
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 6 (0x6)
.maxstack 8
IL_0000: call void Program::EmptyBody()
IL_0005: ret
} // end of method Program::Main
.method private hidebysig static void EmptyBody() cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method Program::EmptyBody
Неудивительно, что MSIL содержит вызов от Main
до EmptyBody
, так как компилятор С# не ожидает встроенных или оптимизированных подобных вызовов. Тем не менее, я думал, что компилятор JIT затем включит или оптимизирует этот вызов. Но это, похоже, не происходит.
Если я запустил вышеуказанную программу и перешел в отладчик в Main
, сгенерированная сборка:
00572621 mov ebp,esp
00572623 cmp dword ptr ds:[4320B84h],0
0057262A je 00572631
0057262C call 73E6AF20
00572631 call dword ptr ds:[4321578h]
Указатель инструкции сразу устанавливается в последнюю строку в 00572631, что является вызовом EmptyBody
. Выйдя в EmptyBody
, создается сгенерированная сборка
00BD2651 mov ebp,esp
00BD2653 cmp dword ptr ds:[4B00B84h],0
00BD265A je 00BD2661
00BD265C call 73E6AF20
00BD2661 nop
00BD2662 pop ebp
00BD2663 ret
Указатель инструкции сразу устанавливается в строку nop
на 00BD2661, что ничего не делает, и я не могу догадаться, почему он сгенерирован в первую очередь.
Учитывая, что два вышеописанных фрагмента сборки содержат один и тот же заголовок с 4 командами, я предполагаю, что только плавная панель входа в систему, где установлен стек и такая настройка. Я очень хочу научиться знать, что будут делать эти повторяющиеся инструкции:
00BD2653 cmp dword ptr ds:[4B00B84h],0
00BD265A je 00BD2661
00BD265C call 73E6AF20
Во всяком случае, главный вопрос: почему компилятор JIT создает сборку, которая вызывает пустой статический метод EmptyBody
?