【问题标题】:How does the .NET VM check for integer overflows?.NET VM 如何检查整数溢出?
【发布时间】:2011-01-03 23:58:15
【问题描述】:

正如我们都知道和喜爱的那样,每次整数溢出时,.NET 都会引发 IntegerOverflow 异常。我认为这是一件非常好的事情。

但我想知道他们是如何做到这么快的。 x86 不会捕获整数溢出,如果其他架构允许这样做,我会感到惊讶。我为 x86 找到的最佳解决方案是在每个算术运算之后放置一条“INTO”指令。但我认为这会导致明显的放缓。

如果可以证明操作不会溢出,他们可以在编译器中进行一些静态检查以避免这种情况。但是当编译器无法确定操作的结果时,性能关键的内部循环呢?

我尝试查看 Mono 源代码,但找不到他们进行这些检查的位置。

那么有没有人知道他们到底在做什么?我真的很想知道。

附带说明:有没有办法查看 .NET JITC 发出的 x86 代码?

【问题讨论】:

  • “每次整数溢出”:仅当使用 IL 指令的检查形式时,例如add.ovf 而不是 add。使用未经检查的指令——这是 C# 至少默认生成的,除非你使用 checked 关键字——溢出只会以我们从 C 中“了解和喜爱”的方式滚动。
  • 附注... NGEN 将生成本机图像机器码... msdn.microsoft.com/en-us/library/6t9t5wcf%28VS.80%29.aspx
  • 这不是一个很大的惩罚。如果溢出异常很少见,处理器将开始快速正确预测这些分支,您几乎不会遇到任何减速(假设您担心循环中的性能)。
  • 我想我听过一个演讲,演讲者说检查是 .NET 的默认设置。可能是我记错了。
  • 是的。 .Net 也没有强制要求,这完全取决于语言(而不是 JIT)编译器。在 VB.Net 中是默认值,在 c# 中不是。

标签: .net jit


【解决方案1】:

开始调试,右键源码,去反汇编。你会看到这样的东西:

      int ix = int.MaxValue;
0000003a  mov         dword ptr [ebp-40h],7FFFFFFFh 
      int jx = 1;
00000041  mov         dword ptr [ebp-44h],1 
      Console.WriteLine(ix + jx);
00000048  mov         ecx,dword ptr [ebp-40h] 
0000004b  add         ecx,dword ptr [ebp-44h] 
0000004e  jno         00000055                 <--- overflow test
00000050  call        6D7ABAD2                 <--- kaboom
00000055  call        6CFE2F40 

换句话说:JIT 编译器生成显式代码来检查溢出。默认关闭。

【讨论】:

    【解决方案2】:

    仅当您在已检查的上下文中时才会抛出它,无论是在源代码中还是作为项目中的设置(这取决于语言)。其结果是输出一条不同的 IL 指令。

    这只是arithmetic overflow 的一般问题的一个具体示例,x86 JIT 实现无疑会在任何此类操作之后插入对相关标志的检查,如果设置了标志则抛出异常的指令。

    说明(以加法为例)是:

    • add 添加两个数字(带有环绕溢出)
    • add.ovf 添加两个数字并捕获有符号溢出
    • add.ovf.un 添加两个数字并捕获无符号溢出

    确实存在一定程度的编译器验证,即常量折叠发生并且结果值必须适合分配的变量。其他静态分析措施是可能的,但可以捕获的内容是有限的。

    如果您希望查看发出的 JIT 代码,只需在混合模式下调试相关代码,然后像查看普通程序一样查看反汇编、堆栈、寄存器。或者去看看 ngen 图像(这很棘手,因为格式很容易改变)。

    请注意,通过 VS 执行此操作,您可能希望正常启动程序(在发布模式下),然后附加调试器,因为 JIT 的结果会有所不同,具体取决于是否附加了调试器以及是否标记了程序集禁止优化(调试版本的默认设置)

    【讨论】:

      猜你喜欢
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多