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
etBar
appels commeBaz
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 deSomeSecurityCriticalMethod
qui est marqué avec l'attribut[MethodImpl(MethodImplOptions.NoInlining)]
? - Pourquoi
GetExecutingAssembly
renvoie un assembly valide lorsqu'il est appelé par les méthodesBaz
etSomeSecurityCriticalMethod
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'appelProgram.Main()
et aucune méthode deClassLib
assenbly, àConsoleApp
doit être retournée.