Mientras jugaba con C#, encontré el siguiente fragmento:
public int F() { try { return 0; } catch (Exception) { return -1; } }Esto genera el siguiente asm :
Program.F() L0000: push ebp L0001: mov ebp, esp L0003: push esi L0004: sub esp, 0x14 L0007: xor eax, eax L0009: mov [ebp-0x18], eax L000c: mov [ebp-0x14], eax L000f: mov [ebp-0x10], eax L0012: mov [ebp-0xc], eax L0015: xor esi, esi L0017: jmp short L0023 L0019: mov esi, 0xffffffff L001e: call 0x6fb2d4d3 L0023: mov eax, esi L0025: lea esp, [ebp-4] L0028: pop esi L0029: pop ebp L002a: ret Y cuando elimino el bloque try and catch :
public int F() { return 0; }entonces la salida generada es:
Program.F() L0000: xor eax, eax L0002: ret Como puede ver, JIT (Release) sabe que no devolverá -1 (no puede encontrar ninguna rama que salte para return -1 ), pero genera el bloque de prueba para el caso de return 0 . La pregunta es si la declaración de devolución puede generar una excepción o ¿por qué JIT genera asm para ella?
En contraste: esto es lo que genera g++ (O2) para C++ .
int f(void *this_) { try { return 0; } catch(...) { return -1; } }Asm
f(void*): xor eax, eax retUna declaración de devolución, en general, puede causar una excepción debido a la naturaleza de propósito general de la expresión permitida en la declaración; en general, una expresión puede causar una excepción.
¿Debe el JIT optimizar el manejo de excepciones sabiendo que la expresión 0 no puede arrojar? Tal vez, en un mundo perfecto. ¿Alguien se queja de esto?