I'm trying to craft a short C# snippet that would illustrate change of Assembly.GetCallingAssembly()
behavior because of JIT-inlining outlined in MSDN. Here's my code so far:
class Program
{
static void Main(string[] args)
{
Console.WriteLine( GetAssembly().FullName );
Console.ReadLine();
}
static Assembly GetAssembly()
{
return System.Reflection.Assembly.GetCallingAssembly();
}
}
which I build in "Release" and start using "Start Without Debugging" - this setup made code from this answer incur inlining. The result I see is
ConsoleApplication2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
so clearly GetAssembly()
is not inlined into Main()
, otherwise I'd see mscorlib
as the calling assembly.
I've reviewed all the inlining criteria and I don't see why GetAssembly()
would not be inlined.
Is it somehow possible to know why exactly JIT compiler decided to not inline a call?
This is the declaration for Assembly.GetCallingAssembly() in .NET 3.5:
The StackCrawlMark enum is interesting, "look for my callers caller" can't work well when the caller is going to be inlined. There's a comment in SSCLI20 source code for thread.cs where the enum gets declared:
Which is a good match for what happens in GetCallingAssembly(), it's a local variable and does indeed gets passed by ref. Not sure what the mechanism is, the jitter can however produce a method attribute named CORINFO_FLG_BAD_INLINEE. Which in turn forces a call to MethodDesc::SetNotInline(). That's a guess, this is very obscure.