2010-03-28 3 views
3

J'ai tester un nouveau comportement 4,0 CLR dans la méthode inline (inline de cross-assemblage) et trouvé des résultats Strage:CLR 4.0 politique en ligne? (Peut-être bug avec MethodImplOptions.NoInlining)

Assemblée ClassLib.dll:

using System.Diagnostics; 
using System; 
using System.Reflection; 
using System.Security; 
using System.Runtime.CompilerServices; 

namespace ClassLib 
{ 
    public static class A 
    { 
    static readonly MethodInfo GetExecuting = 
     typeof(Assembly).GetMethod("GetExecutingAssembly"); 

    public static Assembly Foo(out StackTrace stack) // 13 bytes 
    { 
     // explicit call to GetExecutingAssembly() 
     stack = new StackTrace(); 
     return Assembly.GetExecutingAssembly(); 
    } 

    public static Assembly Bar(out StackTrace stack) // 25 bytes 
    { 
     // reflection call to GetExecutingAssembly() 
     stack = new StackTrace(); 
     return (Assembly) GetExecuting.Invoke(null, null); 
    } 

    public static Assembly Baz(out StackTrace stack) // 9 bytes 
    { 
     stack = new StackTrace(); 
     return null; 
    } 

    public static Assembly Bob(out StackTrace stack) // 13 bytes 
    { 
     // call of non-inlinable method! 
     return SomeSecurityCriticalMethod(out stack); 
    } 

    [SecurityCritical, MethodImpl(MethodImplOptions.NoInlining)] 
    static Assembly SomeSecurityCriticalMethod(out StackTrace stack) 
    { 
     stack = new StackTrace(); 
     return Assembly.GetExecutingAssembly(); 
    } 
    } 
} 

Assemblée ConsoleApp.exe

using System; 
using ClassLib; 
using System.Diagnostics; 

class Program 
{ 
    static void Main() 
    { 
    Console.WriteLine("runtime: {0}", Environment.Version); 

    StackTrace stack; 
    Console.WriteLine("Foo: {0}\n{1}", A.Foo(out stack), stack); 
    Console.WriteLine("Bar: {0}\n{1}", A.Bar(out stack), stack); 
    Console.WriteLine("Baz: {0}\n{1}", A.Baz(out stack), stack); 
    Console.WriteLine("Bob: {0}\n{1}", A.Bob(out stack), stack); 
    } 
} 

Résultats:

runtime: 4.0.30128.1 

Foo: ClassLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
    at ClassLib.A.Foo(StackTrace& stack) 
    at Program.Main() 

Bar: ClassLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
    at ClassLib.A.Bar(StackTrace& stack) 
    at Program.Main() 

Baz: 
    at Program.Main() 

Bob: ClassLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
    at Program.Main() 

Autant de questions sont:

  • Pourquoi JIT n'a pas inline Foo et Bar appels comme Baz fait? Ils sont inférieurs à 32 octets de IL et sont de bons candidats pour l'inline.
  • Pourquoi appel JIT inline de Bob et appel interne de SomeSecurityCriticalMethod qui est marqué avec l'attribut [MethodImpl(MethodImplOptions.NoInlining)]?
  • Pourquoi GetExecutingAssembly renvoie un assembly valide lorsqu'il est appelé par les méthodes Baz et SomeSecurityCriticalMethod en ligne? Je m'attends à ce qu'il effectue la marche de la pile pour détecter l'exécution de l'assemblage, mais la pile ne contiendra que l'appel Program.Main() et aucune méthode de ClassLib assenbly, à ConsoleApp doit être retournée.

Répondre

3

Le CLR 4.0 a des événements ETW pour la plupart des choses et est ici la trace ETW pour Jit qui devrait donner MethodJitInliningFailed raison et here est la façon dont vous affichez les informations de trace