¿Por qué el comstackdor JIT .NET decide no alinear u optimizar las llamadas a métodos estáticos vacíos que no tienen efectos secundarios?

Creo que estoy observando que el comstackdor JIT .NET no integra ni optimiza las llamadas a métodos estáticos vacíos que no tienen efectos secundarios, lo cual es un poco sorprendente dado algunos recursos en línea personalizados.

Mi entorno es Visual Studio 2013 en x64, Windows 8.1, .NET Framework 4.5.

Dado este sencillo progtwig de prueba ( https://ideone.com/2BRCpC )

class Program { static void EmptyBody() { } static void Main() { EmptyBody(); } } 

Una versión de comstackción con optimizaciones del progtwig anterior produce la siguiente MSIL para Main y 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 

No es sorprendente que la MSIL contenga una llamada de Main a EmptyBody , ya que no se espera que el comstackdor de C # EmptyBody o optimice llamadas de esa manera. Sin embargo, pensé que el comstackdor JIT luego alinearía o optimizaría esa llamada. Pero eso no parece suceder.

Si ejecuto el progtwig anterior y entro en el depurador en Main , el ensamblado generado es el siguiente:

 00572621 mov ebp,esp 00572623 cmp dword ptr ds:[4320B84h],0 0057262A je 00572631 0057262C call 73E6AF20 00572631 call dword ptr ds:[4321578h] 

El puntero de instrucción se establece inmediatamente en la última línea en 00572631, que es la llamada a EmptyBody . Al entrar en EmptyBody , se encuentra que el ensamblado generado es

 00BD2651 mov ebp,esp 00BD2653 cmp dword ptr ds:[4B00B84h],0 00BD265A je 00BD2661 00BD265C call 73E6AF20 00BD2661 nop 00BD2662 pop ebp 00BD2663 ret 

El puntero de instrucción se establece inmediatamente en la línea nop en 00BD2661, que no hace nada, y no puedo adivinar por qué se generó en primer lugar.

Dado que los dos fragmentos de ensamblaje anteriores comparten el mismo encabezado de 4 instrucciones, asumo que es solo la placa de la caldera de entrada de método normal donde se configura la stack y tal. Sin embargo, estoy dispuesto a aprender a saber qué harían estas instrucciones recurrentes:

 00BD2653 cmp dword ptr ds:[4B00B84h],0 00BD265A je 00BD2661 00BD265C call 73E6AF20 

De todos modos, la pregunta principal es: ¿Por qué el comstackdor JIT produce un ensamblaje que llama al método estático de cuerpo vacío, EmptyBody ?

Después de profundizar un poco más, resulta que puedo responder esta pregunta yo mismo. Como se explica en http://blogs.msdn.com/b/vancem/archive/2006/02/20/535807.aspx , observar el desensamblaje de una versión de lanzamiento optimizada bajo el depurador afectará de forma predeterminada al comstackdor JIT.

Deseleccionando estos

  • ‘Suprimir la optimización JIT en la carga del módulo’
  • ‘Habilitar solo mi código’

en VS> Herramientas> Depuración> General, se mostrará el resultado de comstackción JIT “real”, que para la llamada a EmptyBody en mi Main anterior es la siguiente:

 004C2620 ret 

Lo que significa que la llamada a EmptyBody se eliminó por completo, que es lo que se esperaba y el mundo sigue siendo un lugar feliz y un tanto predecible para vivir 🙂