我使用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代碼的文章/博客讚賞。