Encontró un error de generación de código en .NET 4 x86 jitter. Es muy inusual, solo falla cuando el código no está optimizado. El código de la máquina se ve así:
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
Un asunto pesado con muchos temporales y duplicación de código, eso es normal para el código no optimizado. La instrucción en 013F04B8 es notable, ahí es donde ocurre la conversión necesaria de sbyte a un entero de 32 bits. La función auxiliar de obtención de matriz devolvió 0x0000000FF, igual a State.BUG, y eso debe convertirse a -1 (0xFFFFFFFF) antes de que se pueda comparar el valor. La instrucción MOVSX es una instrucción Sign eXtension.
Lo mismo sucede nuevamente en 013F04CC, pero esta vez no hay instrucciones MOVSX para hacer la misma conversión. Ahí es donde se caen los chips, la instrucción CMP compara 0xFFFFFFFF con 0x000000FF y eso es falso. Entonces, este es un error de omisión, el generador de código no pudo emitir MOVSX nuevamente para realizar la misma conversión de sbyte a int.
Lo que es particularmente inusual acerca de este error es que funciona correctamente cuando habilita el optimizador, ahora sabe usar MOVSX en ambos casos.
La razón probable de que este error no se haya detectado durante tanto tiempo es el uso de sbyte como el tipo base de la enumeración. Muy raro de hacer. El uso de una matriz multidimensional también es instrumental, la combinación es fatal.
De lo contrario, diría que es un error bastante crítico. Es difícil adivinar cuán extendido podría ser, solo tengo que probar la fluctuación de fase 4.6.1 x86. El x64 y el jitter 3.5 x86 generan un código muy diferente y evitan este error. La solución temporal para continuar es eliminar sbyte como el tipo base enum y dejar que sea el valor predeterminado, int , para que no sea necesaria la extensión de signo.
Puede presentar el error en connect.microsoft.com, el enlace a este Q + A debería ser suficiente para decirles todo lo que necesitan saber. Avísame si no quieres tomarte el tiempo y yo me encargaré.