What's the point of MethodImplOptions.InternalCall?

感情迁移 提交于 2019-11-28 21:09:33

I think a big reason is that it's quite hard to create a new IL instruction and it could affect a lot of tools, including external ones (ILGenerator, ilasm, ildasm, PEVerify, Reflector, PostSharp, …).

But creating a new InternalCall method? That's almost as simple as writing the method in C# (I assume, I didn't look at Rotor to verify) and it doesn't affect anything.

And it's not just about creating it, I think the same applies to maintenance.

I think it was to not over-complicate the CLR. When I first looked into CIL I couldn't help notice the similarities with an assembly language, and more than that, the limited instructions set, almost as if they had made it to run directly on a processor.

In theory, when the CLR JIT's that sample code for Pow you included in your post, it would have to issue itself the native code for the pow instruction, since there's no native instruction (or is it? haven't been up to date with new x86 instruction sets since a few years back). Looking from the performance point of view but also from the implementation point of view, it is much easier to just call into mscorlib for the pow code, than just "paste" it inline.

Or, they could have had a lookup table for common mscorlib functions that are InternalCall and substitute the instruction with a call to the function itself. But then again, not all InternalCall are as easy as that.

I think it was a trade-off for convenience; both on their side, for CLR maintainability, a more uniform CLI standard and to allow some flexibility to callers.

Bottom-line is that I haven't developed the CLR and this is just off the top of my head. Something I would've done, I guess.

The method is native, TRULY native, implemented into the Runtime itself. Don't forget, that CLR comes from C++ after all. It's like in compiler. In real world, CIL is not truly executed. It's JIT-ted and then executed, like a compiler, by a C/C++ runtime. Math.Pow is most probably [speculation] a call into the native C/C++ math.h pow method, and it's implementation-defined - now NET and Mono implement the CLR.

In UnityEngine.dll, [MethodImpl(MethodImplOptions.InternalCall)] is used on most native external methods. These C++ methods however use the Mono C++ CLR Library directly and they can co-operate with C# in way more intimate way than P/INVOKE itself. And way more performant (PInvoke hides some implementation details and makes some hard to understand)

However, the only way to use [MethodImpl(MethodImplOptions.InternalCall)] is if you are the CLR runtime itself - I only tested Mono like this, however. I don't know if it is even possible to alter the Microsoft's CLR Implementation, but with Mono you are free to abuse this feature.

Also, don't mess this with [MethodImpl(MethodImplOptions.Unmanaged)] - it's whole different story.

More about internal calls and how Mono works, here: http://www.mono-project.com/docs/advanced/embedding/

Disclaimer: I am NOT related to Unity or Mono!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!