Encontrei o truque em @GrabYourPitchforks https://github.com/dotnet/coreclr/pull/20386
O JIT pode reconhecer o padrão e gerar código otimizado para tipos selados.
`` `C #
[MethodImpl (MethodImplOptions.NoInlining)]
public static int Is (object obj)
{
if (obj is string str)
return str.Length;
return 7;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static int As(object obj)
{
string str = obj as string;
if (str != null)
return str.Length;
return 7;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static int SafeUnsafe(object obj)
{
if (obj != null && obj.GetType() == typeof(string))
return Unsafe.As<string>(obj).Length;
return 7;
}
<details><summary>See the generated code</summary><p>
```ASM
; Assembly listing for method Program:Is(ref):int
; Emitting BLENDED_CODE for X64 CPU with AVX
; optimized code
; rsp based frame
; partially interruptible
; Final local variable assignments
;
; V00 arg0 [V00,T01] ( 3, 3 ) ref -> rcx class-hnd
; V01 loc0 [V01,T02] ( 3, 2.50) ref -> rax class-hnd
;# V02 OutArgs [V02 ] ( 1, 1 ) lclBlk ( 0) [rsp+0x00]
; V03 tmp1 [V03,T00] ( 5, 6.74) ref -> rax class-hnd
;
; Lcl frame size = 0
G_M12761_IG01:
0F1F440000 nop
G_M12761_IG02:
488BC1 mov rax, rcx
4885C0 test rax, rax
7411 je SHORT G_M12761_IG03
48BA00F50A96FE7F0000 mov rdx, 0x7FFE960AF500
483910 cmp qword ptr [rax], rdx
7402 je SHORT G_M12761_IG03
33C0 xor rax, rax
G_M12761_IG03:
4885C0 test rax, rax
7404 je SHORT G_M12761_IG05
8B4008 mov eax, dword ptr [rax+8]
G_M12761_IG04:
C3 ret
G_M12761_IG05:
B807000000 mov eax, 7
G_M12761_IG06:
C3 ret
; Total bytes of code 45, prolog size 5 for method Program:Is(ref):int
; ============================================================
; Assembly listing for method Program:As(ref):int
; Emitting BLENDED_CODE for X64 CPU with AVX
; optimized code
; rsp based frame
; partially interruptible
; Final local variable assignments
;
; V00 arg0 [V00,T01] ( 3, 3 ) ref -> rcx class-hnd
; V01 loc0 [V01,T02] ( 3, 2.50) ref -> rax class-hnd
;# V02 OutArgs [V02 ] ( 1, 1 ) lclBlk ( 0) [rsp+0x00]
; V03 tmp1 [V03,T00] ( 5, 6.74) ref -> rax class-hnd
;
; Lcl frame size = 0
G_M12497_IG01:
0F1F440000 nop
G_M12497_IG02:
488BC1 mov rax, rcx
4885C0 test rax, rax
7411 je SHORT G_M12497_IG03
48BA00F50A96FE7F0000 mov rdx, 0x7FFE960AF500
483910 cmp qword ptr [rax], rdx
7402 je SHORT G_M12497_IG03
33C0 xor rax, rax
G_M12497_IG03:
4885C0 test rax, rax
7404 je SHORT G_M12497_IG05
8B4008 mov eax, dword ptr [rax+8]
G_M12497_IG04:
C3 ret
G_M12497_IG05:
B807000000 mov eax, 7
G_M12497_IG06:
C3 ret
; Total bytes of code 45, prolog size 5 for method Program:As(ref):int
; ============================================================
; Assembly listing for method Program:SafeUnsafe(ref):int
; Emitting BLENDED_CODE for X64 CPU with AVX
; optimized code
; rsp based frame
; partially interruptible
; Final local variable assignments
;
; V00 arg0 [V00,T00] ( 5, 4 ) ref -> rcx class-hnd
;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [rsp+0x00]
;
; Lcl frame size = 0
G_M6777_IG01:
0F1F440000 nop
G_M6777_IG02:
4885C9 test rcx, rcx
7413 je SHORT G_M6777_IG04
48B800F50A96FE7F0000 mov rax, 0x7FFE960AF500
483901 cmp qword ptr [rcx], rax
7504 jne SHORT G_M6777_IG04
8B4108 mov eax, dword ptr [rcx+8]
G_M6777_IG03:
C3 ret
G_M6777_IG04:
B807000000 mov eax, 7
G_M6777_IG05:
C3 ret
; Total bytes of code 35, prolog size 5 for method Program:SafeUnsafe(ref):int
; ============================================================
E para economizar rax
seria bom ter
cmp qword ptr [rcx], 0x7FFE960AF500
ao invés de
mov rax, 0x7FFE960AF500
cmp qword ptr [rcx], rax
Esta é uma área conhecida para melhorias (consulte dotnet / runtime # 9117).
A maioria das instruções x64 não pode lidar com operandos constantes literais grandes, e é por isso que você vê mov; cmp
como você viu acima.
A semana dos dups :)
Fechando.
É útil ter (e ser lembrado) esses tipos de exemplos.
Por favor, não deixe de relatar coisas porque você está preocupado em relatar algo já conhecido. Às vezes, coisas de aparência semelhante não são tão semelhantes no final.
Comentários muito úteis
É útil ter (e ser lembrado) esses tipos de exemplos.
Por favor, não deixe de relatar coisas porque você está preocupado em relatar algo já conhecido. Às vezes, coisas de aparência semelhante não são tão semelhantes no final.