C# 发射MSIL以发射MSIL会遇到JIT限制
所以我想回答这个问题,并决定发出MSIL代码来进行整数加法。因为这是成功的,所以我决定发出MSIL代码,这将发出我的第一个代码。因此,调用代码构造了一个方法,该方法构造了一个调用C# 发射MSIL以发射MSIL会遇到JIT限制,c#,cil,reflection.emit,C#,Cil,Reflection.emit,所以我想回答这个问题,并决定发出MSIL代码来进行整数加法。因为这是成功的,所以我决定发出MSIL代码,这将发出我的第一个代码。因此,调用代码构造了一个方法,该方法构造了一个调用int.op\u Addition的方法。这失败得很惨,JIT抱怨我做得太过分了!哼 异常为System.SystemException:{“JIT编译器遇到内部限制。”}在调用动态方法时位于最后一行 我的问题是,我正确地假设JIT以某种方式不允许发出代码来发出代码。另一种选择是,我犯了一个错误,这很可能是错误的,但我检
int.op\u Addition
的方法。这失败得很惨,JIT抱怨我做得太过分了!哼
异常为System.SystemException:{“JIT编译器遇到内部限制。”}
在调用动态方法时位于最后一行
我的问题是,我正确地假设JIT以某种方式不允许发出代码来发出代码。另一种选择是,我犯了一个错误,这很可能是错误的,但我检查了我的代码与Reflector
生成的MSIL代码
以下是代码,供您娱乐:
class Program
{
static void Main(string[] args)
{
int z2=Add2(1, 2);
// z2 = "JIT Compiler encountered an internal limitation."
}
// Emit MSIL to emit MSIL
public static int Add2(int x, int y)
{
Type delegate_type=typeof(Func<int, int, int>);
DynamicMethod method=new DynamicMethod(typeof(Program).ToString()+".GenAdd",
typeof(int),
new Type[] { typeof(int), typeof(int) }, typeof(Program));
ILGenerator generator=method.GetILGenerator();
LocalBuilder method1=generator.DeclareLocal(typeof(DynamicMethod));
LocalBuilder generator1=generator.DeclareLocal(typeof(ILGenerator));
LocalBuilder add1=generator.DeclareLocal(typeof(Func<int, int, int>));
LocalBuilder args1=generator.DeclareLocal(typeof(Type[]));
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(object).GetMethod("ToString",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Instance));
generator.Emit(OpCodes.Ldstr, ".op_Addition");
generator.Emit(OpCodes.Call,
typeof(string).GetMethod("Concat",
new Type[] { typeof(string), typeof(string) } ));
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Ldc_I4, 2);
generator.Emit(OpCodes.Newarr, typeof(Type));
generator.Emit(OpCodes.Stloc_3);
generator.Emit(OpCodes.Ldloc_3);
generator.Emit(OpCodes.Ldc_I4, 0);
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Stelem_Ref);
generator.Emit(OpCodes.Ldloc_3);
generator.Emit(OpCodes.Ldc_I4, 1);
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Stelem_Ref);
generator.Emit(OpCodes.Ldloc_3);
generator.Emit(OpCodes.Ldtoken, typeof(Program));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Newobj,
typeof(DynamicMethod).GetConstructor(
new Type[] { typeof(string), typeof(Type), typeof(Type[]) }));
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Callvirt,
typeof(DynamicMethod).GetMethod("GetILGenerator",
Type.EmptyTypes));
generator.Emit(OpCodes.Stloc_1);
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("DeclareLocal",
new Type[] { typeof(Type) }));
generator.Emit(OpCodes.Pop);
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ldarg_0",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ldarg_1",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Add",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Stloc_0",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ldloc_0",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ret",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ldtoken, typeof(Func<int, int, int>));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(DynamicMethod).GetMethod("CreateDelegate",
new Type[] { typeof(Type)} ));
generator.Emit(OpCodes.Isinst, typeof(Func<int, int, int>));
generator.Emit(OpCodes.Stloc_2);
generator.Emit(OpCodes.Ldloc_2);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Callvirt,
typeof(Func<int, int, int>).GetMethod("Invoke",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Instance));
generator.Emit(OpCodes.Ret);
Func<int, int, int> add2=method.CreateDelegate(typeof(Func<int, int, int>)) as Func<int, int, int>;
return add2(x, y);
}
}
我非常确定JIT能够编译使用反射的代码。否则,您将永远无法使用
Reflection.Emit
。生成的MSIL与C#编译器生成的MSIL经过相同的JIT过程
在CAS检查方面有一点不同,但我看不到任何迹象表明您首先是在部分信任场景中操作的
我看到这一行:
generator.Emit(OpCodes.Newobj,
typeof(DynamicMethod).GetConstructor(
new Type[] { typeof(string), typeof(Type), typeof(Type[]) }));
它定位创建匿名托管方法的DynamicMethod(string,Type,Type[])
构造函数。但是在Add1
中,您有
DynamicMethod method = new DynamicMethod(typeof(int).ToString()+".op_Addition",
typeof(int),
new Type[] { typeof(int), typeof(int) },
typeof(Program));
它调用四个参数DynamicMethod
构造函数,向类型程序
添加一个方法
因此,当您使用
newobj
时,操作数堆栈上的类型完全不匹配。如果代码有问题,它将生成一个系统。SystemException:{“公共语言运行库检测到一个无效程序”。}
多亏了Ben,代码现在可以工作了,而且,JIT毕竟没有问题。仅供参考-以下是代码竞赛帖子:我将使用此构造函数公共动态方法(字符串名称、类型returnType、类型[]参数类型、类型所有者)代码>。你是对的。现在可以了。
DynamicMethod method = new DynamicMethod(typeof(int).ToString()+".op_Addition",
typeof(int),
new Type[] { typeof(int), typeof(int) },
typeof(Program));