1

私たちがよく知っているように、.NET はIntegerOverflow整数がオーバーフローするたびに例外をスローします。これはとても良いことだと思います。

しかし、どうやってこれを速くするのだろうか。x86 は整数のオーバーフローをトラップしません。他のアーキテクチャでそれができるとしたら、私は驚きます。私が x86 で見つけた最善の解決策は、すべての算術演算の後に「INTO」命令を配置することです。しかし、それは顕著な減速につながると思います。

操作がオーバーフローできないことが証明できる場合は、コンパイラで静的チェックを行ってこれを回避できます。しかし、コンパイラが操作の結果を判断できない場合、パフォーマンスが重要な内部ループはどうなるでしょうか?

Mono のソースを見てみましたが、これらのチェックを行っている場所が見つかりませんでした。

それで、彼らが実際に何をしているのか、誰かが手がかりを持っていますか? 本当に知りたいです。

余談ですが、.NET JITC が出力する x86 コードを確認する方法はありますか?

4

2 に答える 2

3

デバッグを開始し、ソースを右クリックして、逆アセンブリに移動します。次のようなものが表示されます。

      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コンパイラはオーバーフローをチェックするための明示的なコードを生成します。これはデフォルトでオフになっています。

于 2010-01-12T01:18:32.193 に答える
2

ソースまたはプロジェクトの設定のいずれかで、チェックされたコンテキスト内にいる場合にのみスローされます(これは言語に依存します)。その結果、別のIL命令が出力されます。

これは算術オーバーフローの一般的な問題の特定の例であり、x86 JIT実装は、フラグが設定されている場合に例外をスローする命令を使用して、そのような操作の後に関連するフラグのチェックを挿入することは間違いありません。

手順(例として加算を使用)は次のとおりです。

  • 追加して2つの数値を追加します(ラップアラウンドオーバーフローあり)
  • add.ovfを使用して、2つの数値を追加し、署名されたオーバーフローをトラップします
  • add.ovf.unを使用して、2つの数値を追加し、符号なしオーバーフローをトラップします

定数畳み込みが発生し、結果の値が割り当てられた変数に収まらなければならないという点で、確かに一定レベルのコンパイラ検証があります。他の静的分析手段も可能ですが、トラップできるものには制限があります。

放出されたJITコードを確認したい場合は、関連するコードを混合モードでデバッグし、通常のプログラムと同じように逆アセンブル、スタック、レジスターを確認してください。または、ngenイメージを確認してください(フォーマットは変更される可能性があるため、これは注意が必要です)。

VSを介してこれを行う場合は、プログラムを通常どおりに(リリースモードで)起動してから、デバッガーを接続することをお勧めします。これは、デバッガーが接続されているかどうか、およびアセンブリが最適化を許可しないとマークされているかどうかによってJITの結果が異なるためです。 (デバッグビルドのデフォルト)

于 2010-01-12T01:13:40.387 に答える