Embedding CLR 4.0 policy? (possibly error with MethodImplOptions.NoInlining)

I tested some CLR 4.0 behavior when embedding a method (cross-build inlining) and found some addition results:

Assembly 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();
    }
  }
}

Assembly 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);
  }
}

Results:

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()

So the questions are:

  • Why not support JIT Fooand Barcalls like Baz? They are below 32 bytes of IL and are good candidates for embedding.
  • Why do I need a JIT call Boband an internal call SomeSecurityCriticalMethodthat is marked with an attribute [MethodImpl(MethodImplOptions.NoInlining)]?
  • GetExecutingAssembly , inlined Baz SomeSecurityCriticalMethod? , , , Program.Main(), ClassLib assenbly, to ConsoleApp .
+3
1

CLR 4.0 ETW , ETW Jit, MethodJitInliningFailed reason -

+3

Source: https://habr.com/ru/post/1738874/


All Articles