8

を使用してコンパイラに取り組んでいSystem.Reflection.Emitますが、理解できない JIT 制限エラーが発生しています。この問題は、関数ハンドルの実装で発生します。つまり、次のコードを生成します

function foo() { }
f = foo;
f();

f私の制御を超えた仕様により、言語は動的に型付けされるため、コンパイル時に予想される引数の数を知ることができません。Ldftnこれに対抗するために、 for を発行するのではなくfoo、新しいメソッド を生成します。このメソッドλfooは、呼び出し式で指定された引数の配列を取り、それらを for の評価スタックにプッシュしますfoo。それはCLRで許可されていますか?

私が今得ているのは、「JIT で内部制限が発生しました」という例外 (または、アセンブリを保存してメモリから呼び出す代わりに実行した場合は「CLR が無効なプログラムを検出しました」) で、それがλfoo. これは私が生成している IL です。

.method private instance class [MylibInterop]MylibInterop.MylibValue 
        'λfoo'(class [MylibInterop]MylibInterop.MylibValue[] A_1) cil managed
{
  // Code size       90 (0x5a)
  .maxstack  10
  .locals init (int32 V_0,
           int32 V_1)
  IL_0000:  ldarg.1
  IL_0001:  call       instance int32 [mscorlib]System.Array::get_Length()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4     0x0
  IL_000d:  ble        IL_001d
  IL_0012:  ldstr      "Too many arguments to lambda call"
  IL_0017:  newobj     instance void [mscorlib]System.Exception::.ctor(string)
  IL_001c:  throw
  IL_001d:  ldarg.0
  IL_001e:  ldc.i4.0
  IL_001f:  stloc.1
  IL_0020:  ldloc.0
  IL_0021:  newobj     instance void [MylibInterop]MylibInterop.MylibValue::.ctor(int32)
  IL_0026:  ldloc.1
  IL_0027:  ldloc.0
  IL_0028:  bge        IL_003d
  IL_002d:  ldarg.1
  IL_002e:  ldloc.1
  IL_002f:  ldelem     [MylibInterop]MylibInterop.MylibValue
  IL_0034:  ldloc.1
  IL_0035:  ldc.i4.1
  IL_0036:  add
  IL_0037:  stloc.1
  IL_0038:  br         IL_0026
  IL_003d:  ldloc.0
  IL_003e:  stloc.1
  IL_003f:  ldloc.1
  IL_0040:  ldc.i4     0x0
  IL_0045:  bge        IL_0054
  IL_004a:  ldnull
  IL_004b:  ldloc.1
  IL_004c:  ldc.i4.1
  IL_004d:  add
  IL_004e:  stloc.1
  IL_004f:  br         IL_003f
  IL_0054:  call       instance class [MylibInterop]MylibInterop.MylibValue debug.Program::foo(class [MylibInterop]MylibInterop.MylibValue)
  IL_0059:  ret
} // end of method Program::'λfoo'
4

1 に答える 1

7

@leppieはコメントでそれを得ました:スタックは決定論的である必要があります。それは私が生成していたコードには含まれていません(正しい数の引数をプッシュしていることがわかっていても)。コンパイラーがループを展開するのに十分な情報を持っていたため(したがって、生成されたILの定数)、決定論的なスタックを生成するため、これを回避することができました。

于 2013-02-04T17:08:55.820 に答える