Prevención de la inserción de JIT en un método


Tengo una especie de situación única. He estado trabajando en una biblioteca de código abierto para enviar correos electrónicos. En esta biblioteca, necesito una forma confiable de obtener el método de llamada. He hecho esto con un StackTrace analizando los objetos StackFrame dentro de él. Esto funciona sin problemas en un proyecto de modo de depuración donde las optimizaciones están desactivadas.

El problema ocurre cuando cambio al modo release donde las optimizaciones están activadas. El seguimiento de la pila se ve así:

> FindActionName at offset 66 in file:line:column <filename unknown>:0:0
> Email at offset 296 in file:line:column <filename unknown>:0:0
> CallingEmailFromRealControllerShouldFindMailersActionName at offset 184
     in file:line:column <filename unknown>:0:0
> _InvokeMethodFast at offset 0 in file:line:column <filename unknown>:0:0
> InvokeMethodFast at offset 152 in file:line:column <filename unknown>:0:0
...

Esto se toma de una prueba unitaria fallida. En la línea 3 de esta traza, debería ver un método llamado TestEmail que está definido en otro lugar, pero creo que el JITter está incrustado. He leído que puedes evitar la inserción haciendo virtual un método, pero esto no funciona. ¿Alguien sabe de un método confiable para prevenir la incrustación de métodos para que su método se muestre en un seguimiento de pila?

Author: Scott Anderson, 2011-03-02

2 answers

Usted podría utilizar MethodImplAttribute y especificar MethodImplOptions.NoInlining.

[MethodImpl(MethodImplOptions.NoInlining)]
void YourMethod()
{
    // do something
}

Tenga en cuenta que esto todavía no garantiza que pueda obtener el método de llamada real como se ve en el código fuente. Su método no estar en línea, pero su método de llamada que podría estar en línea en su propia persona, etc, etc.

 30
Author: LukeH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-02 15:02:38

Puede utilizar parámetros adicionales marcados con System.Runtime.CompilerServices.CallerMemberNameAttribute y son hermanos CallerFilePath y CallerLineNumber. Si lo entiendo correctamente esto debería obtener el nombre del método correcto, no importa lo que está en línea y lo que no. Solo obtendrá el nombre del método sin embargo, no veo nada para obtener el nombre de la clase / ensamblado, etc.

No hace falta decirlo, pero solo para estar seguro... algo como esto debería no ser usado fuera de logging/diagnostics.

Formas adecuadas de hacer esto probablemente sería:

  • Pase la información requerida como parámetro
  • Almacenar temporalmente la información requerida en Thread.ExecutionContext al llamar a la función

Me doy cuenta de que esto probablemente no será de ninguna ayuda para Scott después de todo este tiempo, pero tal vez alguien más pueda beneficiarse de ello.

 5
Author: Paul Groke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-20 07:54:51