我使用ILGenerator编写的数组访问操作很简单。当使用这个确切的代码创建方法时,我打开反汇编,没关系,没有数组边界检查。DynamicAssembly中的数组边界检查仅在评估堆栈为空时有效
但是,当我第一次将其他类的实例放在评估堆栈上时,然后运行for循环,它会进行数组边界检查。我正在发布。
任何想法为什么?我已经阅读博客文章数组边界检查:http://blogs.msdn.com/b/clrcodegeneration/archive/2009/08/13/array-bounds-check-elimination-in-the-clr.aspx
// Uncomment this to enable bound checks, type of arg0 is some my class
//il.Emit(OpCodes.Ldarg_0);
var startLbl = il.DefineLabel();
var testLbl = il.DefineLabel();
var index = il.DeclareLocal(typeof(Int32));
var arr = il.DeclareLocal(typeof(Int32).MakeArrayType());
// arr = new int[4];
il.Emit(OpCodes.Ldc_I4_4);
il.Emit(OpCodes.Newarr, typeof(Int32));
il.Emit(OpCodes.Stloc, arr);
// Index = 0
il.Emit(OpCodes.Ldc_I4_0); // Push index
il.Emit(OpCodes.Stloc, index); // Pop index, store
il.Emit(OpCodes.Br_S, testLbl); // Go to test
// Begin for
il.MarkLabel(startLbl);
// Load array, index
il.Emit(OpCodes.Ldloc, arr);
il.Emit(OpCodes.Ldloc, index);
// Now on stack: array, index
// Load element
il.Emit(OpCodes.Ldelem_I4);
// Nothing here now, later some function call
il.Emit(OpCodes.Pop);
// Index++
il.Emit(OpCodes.Ldloc, index);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stloc, index);
il.MarkLabel(testLbl);
// Load index, count, test for end
il.Emit(OpCodes.Ldloc, index);
il.Emit(OpCodes.Ldloc, arr);
il.Emit(OpCodes.Ldlen); // Push len
il.Emit(OpCodes.Conv_I4); // Push len
il.Emit(OpCodes.Blt_S, startLbl);
// End for
// Remove instance added on top
//il.Emit(OpCodes.Pop);
正如我产生IL代码,最好保持的类的实例上计算堆栈或局部变量?
例如我得到实例,通过领域,每个领域做任何事情,而不是回报。我只是将实例保存在堆栈中,并在读取下一个字段之前调用Emit(OpCodes.Dup)。但这似乎是错误的(至少在上面提到的情况下)。
任何关于生成(高效/格式良好)IL代码的文章/博客赞赏。