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