.NET JIT 编译器是否为使用不同枚举进行参数化的泛型生成不同的代码?
如果我编写(或使用)一个泛型类(例如 List),并使用两种不同的枚举类型对其进行参数化,我会得到两份 JITted 代码副本吗?鉴于以下文章讨论了 JITter 如何为引用类型生成一份副本以及为每种值类型生成一份副本,我认为这可以归结为“为了 JITting 的目的,每个特定枚举是否被视为不同的值类型?”
http://msdn.microsoft.com/en-us/library/ms379564%28v=vs.80%29.aspx#csharp_generics_topic1
在 C# 代码中:
using System.Collections.Generic;
namespace Z
{
class Program
{
enum A {a}
enum B {b}
class C<T>
{
}
static void Main(string[] args)
{
var x = new C<A>();
var y = new C<B>(); // does this JIT a new C constructor for enum type B?
}
}
}
我有兴趣了解这一点,而且还专门针对 .NET CF 3.5 (WindowsCE) JIT 编译器(编辑:因为我对可能的代码膨胀影响感兴趣)。关于找出这个问题的最佳方法有什么建议吗?我正在考虑在 C 类中编写一个 P/Invokes 本机代码的函数,我可以在其中闯入调试器并检查调用堆栈 - 特别是返回地址,但也许有人可以根据我的语言规则给出权威的回答我不知道...
If I write (or use) a generic class, e.g. List, and parameterize it with two different enumerated types, will I get two copies of code JITted? Given the following articles that discuss the how the JITter generates one copy for reference types, and one copy for each value type, I think this boils down to, "Is each specific enum considered a different value type for the purpose of JITting?"
http://msdn.microsoft.com/en-us/library/ms379564%28v=vs.80%29.aspx#csharp_generics_topic1
In C# code:
using System.Collections.Generic;
namespace Z
{
class Program
{
enum A {a}
enum B {b}
class C<T>
{
}
static void Main(string[] args)
{
var x = new C<A>();
var y = new C<B>(); // does this JIT a new C constructor for enum type B?
}
}
}
I'm interested to know this in general, but also specifically for the .NET CF 3.5 (WindowsCE) JIT compiler (EDIT: because I'm interested in possible code bloat implications). Any suggestions on the best way to find this out? I was thinking of writing a function in class C that P/Invokes to native code, where I can break into the debugger and examine the callstack - specifically the return address, but perhaps someone can answer authoritatively based on the language rules of which I'm not aware...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因此,我继续组合了一个 P/Invoke 函数,以便从 C.Test 函数进行调用。我闯入本机函数中的调试器(支持托管和本机调试的桌面窗口),然后进入汇编,然后跟踪本机函数中的 RET 指令。 RET之后的EIP(指令指针)与返回两个不同的例程一致,一个用于C A.Test,另一个用于C B.Test。通过这两个函数对通用本机函数(带有我的断点)的多次调用显示了一致的结果。此外,RET后的EIP是0x2E0246和0x2E02BE,它们彼此接近,并且也没有映射到加载的DLL的地址空间。这向我表明它们是 JITted 的,并且 JITted 的时间彼此接近,并且 JITted 方法的大小很小(正如预期的那样)。
因此,至少对于桌面而言,答案是使用不同的枚举 JIT 模板化泛型到不同的例程。
So I went ahead and put together a P/Invoke function to call from a C<T>.Test function. I broke into the debugger (desktop windows supporting managed and native debugging) in the native function, then dropped to assembly, then tracked past the RET instruction from my native function. The EIP (instruction pointer) after the RET was consistent with returning to TWO DIFFERENT routines, one for C<A>.Test, and the other for C<B>.Test. Multiple calls through these two functions to the common native function (with my breakpoint) showed consistent results. Further, the post RET EIPs were 0x2E0246 and 0x2E02BE, which are near each other and also not mapped to a loaded DLLs's address space. This indicates to me that they were JITted, and JITted close in time to each other, and the size of the JITted methods are small (as expected).
So the answer, at least for the desktop, is that generics templated with different enums JIT to different routines.