为什么我的调用Assembly.GetCallingAssembly()的方法不是JIT内联的? [英] Why is my method calling Assembly.GetCallingAssembly() not JIT-inlined?

查看:220
本文介绍了为什么我的调用Assembly.GetCallingAssembly()的方法不是JIT内联的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个简短的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆