5

バックグラウンド

Compilerが「フィールドなどの生成コードを省略する」ことを知っていint foo = 0;ます。これは、メモリアロケータがフィールドをデフォルト値に初期化するためです。参照

        class Foo
        {
            public int a = 1;
            public int b = 0;
        }
        Foo..ctor:
        IL_0000:  ldarg.0     
        IL_0001:  ldc.i4.1
        IL_0002:  stfld       UserQuery+Foo.a // There is no b.
        IL_0007:  ldarg.0
        IL_0008:  call        System.Object..ctor
        IL_000D:  ret

また、「コンパイラは.locals init、ローカル変数を使用するすべてのメソッドを自動的に追加します。これは、メソッドの実行を開始する前に、JIT がすべてのローカル変数を初期化するコードを挿入する必要があることを示しています。」参照

質問

int foo = 0;コンパイラがローカル変数などの IL の生成を省略しないのはなぜ.locals initですか? (フィールドとの一貫性のため?)

(C#仕様では、ローカル変数を確実に割り当てる必要があることを理解しています。それで問題ありません。)

(参照したリンクには、.locals init必要な理由と、C# 仕様でローカルを初期化する必要がある理由が記載されています。ただし、デフォルト値を初期化するための追加の IL 命令が存在しなければならない理由は記載されていません。検証プロセスは.locals init既に保証されているため)

void Main()
{
    int a = 0;
    int b = 1;
    int c = 0;
    int d = a + b + c;
    d++;
}

.maxstack 2
.locals init (int a, int b, int c, int d)

IL_0000:  ldc.i4.0    
IL_0001:  stloc.0     // a (Can be optimized away)
IL_0002:  ldc.i4.1    
IL_0003:  stloc.1     // b
IL_0004:  ldc.i4.0    
IL_0005:  stloc.2     // c (Can be optimized away)
IL_0006:  ldloc.0     // a
IL_0007:  ldloc.1     // b
IL_0008:  add         
IL_0009:  ldloc.2     // c
IL_000A:  add         
IL_000B:  stloc.3     // d
IL_000C:  ldloc.3     // d
IL_000D:  ldc.i4.1    
IL_000E:  add         
IL_000F:  stloc.3     // d
4

1 に答える 1

1

int foo = 0;コンパイラがローカル変数などの IL の生成を省略しないのはなぜ.locals initですか?

なぜそれが必要なのですか?これは実際に検証したわけではありませんが、不要な初期化を削除した場合、JIT コンパイラが別のネイティブ コードを生成した場合は驚くでしょう。

これが意味することは、この最適化を C# コンパイラに追加する唯一の利点は、JIT コンパイルがわずかに高速になることです (処理する IL コードの量が少なくなるため)。C# コンパイラの作成者は、このようなわずかな利点のためにこの最適化を行うことは価値がないと考えているようです。

于 2013-06-24T15:21:07.360 に答える