我在@GrabYourPitchforks https://github.com/dotnet/coreclr/pull/20386 中找到了诀窍
JIT 可以识别模式并为密封类型生成优化代码。
```C#
[MethodImpl(MethodImplOptions.NoInlining)]
公共静态 int Is(object obj)
{
if (obj 是字符串 str)
返回字符串长度;
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
; ============================================================
为了节省rax
最好有
cmp qword ptr [rcx], 0x7FFE960AF500
代替
mov rax, 0x7FFE960AF500
cmp qword ptr [rcx], rax
这是一个已知的改进领域(请参阅 dotnet/runtime#9117)。
大多数 x64 指令无法处理大型文字常量操作数,这就是为什么您会像上面那样看到mov; cmp
。
重复的一周:)
关闭。
拥有(并被提醒)这些类型的例子很有用。
请不要因为担心报道已知的事情而拒绝报道。 有时看起来相似的东西最终并不完全相似。
最有用的评论
拥有(并被提醒)这些类型的例子很有用。
请不要因为担心报道已知的事情而拒绝报道。 有时看起来相似的东西最终并不完全相似。