我在这篇文章中犯了错误吗;I’我没看见

本文关键字:看见 错误 文章 | 更新日期: 2023-09-27 17:57:49

我正在使用System.Reflection.Emit开发编译器,但我遇到了无法解决的JIT限制错误。这个问题发生在我的函数句柄实现中。即生成的代码

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

由于规范超出了我的控制范围,该语言是动态类型的,所以我不知道f在编译时需要多少个参数。为了应对这种情况,我生成了一个新方法λfoo,而不是为foo发出Ldftn,该方法接受调用表达式中给定的参数数组,并将它们推送到foo的eval堆栈中。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'

我在这篇文章中犯了错误吗;I’我没看见

@leppie在注释中得到了它:堆栈需要是确定性的;它不在我生成的代码中(即使我知道它推送了正确数量的args)。我之所以能够绕过这一点,是因为编译器有足够的信息来展开循环(因此生成的IL中的常量),从而生成一个确定性堆栈。