为什么我的调用Assembly.GetCallingAssembly()的方法不是JIT内联的? [英] Why is my method calling Assembly.GetCallingAssembly() not JIT-inlined?
问题描述
我正在尝试编写一个简短的C#代码段,以说明由于JIT内联 .到目前为止,这是我的代码:
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
很显然,GetAssembly()
没有内联到Main()
中,否则我会以mscorlib
作为调用程序集.
so clearly GetAssembly()
is not inlined into Main()
, otherwise I'd see mscorlib
as the calling assembly.
我已经查看了所有内联条件,但看不到为什么不内联GetAssembly()
.
I've reviewed all the inlining criteria and I don't see why GetAssembly()
would not be inlined.
是否有可能知道为什么确切的JIT编译器决定不内联调用?
Is it somehow possible to know why exactly JIT compiler decided to not inline a call?
推荐答案
这是.NET 3.5中Assembly.GetCallingAssembly()的声明:
This is the declaration for Assembly.GetCallingAssembly() in .NET 3.5:
[MethodImpl(MethodImplOptions.NoInlining)]
public static Assembly GetCallingAssembly()
{
StackCrawlMark lookForMyCallersCaller = StackCrawlMark.LookForMyCallersCaller;
return nGetExecutingAssembly(ref lookForMyCallersCaller);
}
StackCrawlMark枚举很有趣,当要内联调用者时,寻找我的调用者调用者"不能很好地工作.在SSCLI20源代码中有一个注释用于thread.cs,其中声明了枚举:
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:
声明此枚举类型的局部变量并将其通过ref传递到需要进行堆栈爬网的函数中,既可以防止被调用方内联[sic],又可以将ESP点传递给堆栈爬网到
declaring a local var of this enum type and passing it by ref into a function that needs to do a stack crawl will both prevent inlining of the calle [sic] and pass an ESP point to stack crawl to
这与GetCallingAssembly()中发生的情况非常匹配,它是一个局部变量,确实确实由ref传递.不确定机制是什么,但是抖动会产生一个名为CORINFO_FLG_BAD_INLINEE的方法属性.依次强制调用MethodDesc :: SetNotInline().那是个猜测,这非常晦涩.
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.
这篇关于为什么我的调用Assembly.GetCallingAssembly()的方法不是JIT内联的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!