Anda menemukan bug pembuatan kode di .NET 4 x86 jitter. Ini sangat luar biasa, hanya gagal ketika kode tidak dioptimalkan. Kode mesin terlihat seperti ini:
State a = s[0, 0];
013F04A9 push 0 ; index 2 = 0
013F04AB mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04AE xor edx,edx ; index 1 = 0
013F04B0 call 013F0058 ; eax = s[0, 0]
013F04B5 mov dword ptr [ebp-4Ch],eax ; $temp1 = eax
013F04B8 movsx eax,byte ptr [ebp-4Ch] ; convert sbyte to int
013F04BC mov dword ptr [ebp-44h],eax ; a = s[0, 0]
Console.WriteLine(a == s[0, 0]); // False
013F04BF mov eax,dword ptr [ebp-44h] ; a
013F04C2 mov dword ptr [ebp-50h],eax ; $temp2 = a
013F04C5 push 0 ; index 2 = 0
013F04C7 mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04CA xor edx,edx ; index 1 = 0
013F04CC call 013F0058 ; eax = s[0, 0]
013F04D1 mov dword ptr [ebp-54h],eax ; $temp3 = eax
; <=== Bug here!
013F04D4 mov eax,dword ptr [ebp-50h] ; a == s[0, 0]
013F04D7 cmp eax,dword ptr [ebp-54h]
013F04DA sete cl
013F04DD movzx ecx,cl
013F04E0 call 731C28F4
Perselingkuhan dengan banyak temporer dan duplikasi kode, itu normal untuk kode yang tidak dioptimalkan. Instruksi pada 013F04B8 terkenal, di situlah konversi yang diperlukan dari sbyte ke integer 32-bit terjadi. Fungsi pembantu pengambil array mengembalikan 0x0000000FF, sama dengan State.BUG, dan yang perlu dikonversi ke -1 (0xFFFFFFFF) sebelum nilainya dapat dibandingkan. Instruksi MOVSX adalah instruksi Sign eXtension.
Hal yang sama terjadi lagi di 013F04CC, tetapi kali ini tidak ada instruksi MOVSX untuk melakukan konversi yang sama. Di situlah chip jatuh, instruksi CMP membandingkan 0xFFFFFFFF dengan 0x000000FF dan itu salah. Jadi ini adalah kesalahan kelalaian, pembuat kode gagal memancarkan MOVSX lagi untuk melakukan konversi yang sama ke konversi int.
Apa yang sangat tidak biasa tentang bug ini adalah bahwa ini berfungsi dengan benar ketika Anda mengaktifkan optimizer, sekarang tahu untuk menggunakan MOVSX dalam kedua kasus.
Kemungkinan alasan bahwa bug ini tidak terdeteksi begitu lama adalah penggunaan sbyte sebagai tipe dasar dari enum. Cukup langka untuk dilakukan. Menggunakan array multi dimensi juga penting, kombinasi ini fatal.
Kalau tidak, bug yang cukup kritis akan saya katakan. Seberapa luas itu mungkin sulit ditebak, saya hanya memiliki jitter 4.6.1 x86 untuk diuji. Jitter x64 dan 3.5 x86 menghasilkan kode yang sangat berbeda dan menghindari bug ini. Solusi sementara untuk melanjutkan adalah menghapus sbyte sebagai tipe enum base dan membiarkannya menjadi default, int , jadi tidak perlu ekstensi tanda.
Anda dapat mengajukan bug di connect.microsoft.com, menautkan ke Q + A ini harus cukup untuk memberi tahu mereka segala yang perlu mereka ketahui. Beritahu saya jika Anda tidak ingin meluangkan waktu dan saya akan membereskannya.