-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Description
It appears that static initialization of Default instances of EqualityComparer for primitives is not folded in compile-time.
I'm not sure if it's intended behavior but I do remember NativeAOT having somewhat similar capability to pre-initialize cctors under certain conditions.
Consider the following type:
readonly record struct Report(
ulong Successful,
ulong Failed,
float MegabytesPerSecond,
float RPS);and its generated GetHashCode() implementation
[CompilerGenerated]
public override int GetHashCode()
{
return ((
EqualityComparer<ulong>.Default.GetHashCode(<Successful>k__BackingField) * -1521134295 +
EqualityComparer<ulong>.Default.GetHashCode(<Failed>k__BackingField)) * -1521134295 +
EqualityComparer<float>.Default.GetHashCode(<MegabytesPerSecond>k__BackingField)) * -1521134295 +
EqualityComparer<float>.Default.GetHashCode(<RPS>k__BackingField);
}Configuration
.NET SDK:
Version: 8.0.100-preview.2.23102.11
Commit: 5c7737d740
Runtime Environment:
OS Name: Mac OS X
OS Version: 13.2
OS Platform: Darwin
RID: osx.13-arm64
Base Path: /usr/local/share/dotnet/sdk/8.0.100-preview.2.23102.11/
Host:
Version: 8.0.0-alpha.1.23080.2
Architecture: arm64
Commit: 9529803ae2
<IlcOptimizationPreference>Speed</IlcOptimizationPreference>
Disassembled with Ghidra 10.2.2 with aggressive instruction finder and relocs resolver turned on (maybe there's a less roundabout option for NativeAOT?).
Analysis
Given the above code, the produced assembly code ends up as below:
_fram0_http_bench_Report__GetHashCode XREF[2]: Entry Point(*),
_http_bench_Report__GetHashCode _unbox_http_bench_Report__GetHas
100092a60 fd 7b bc a9 stp x29,x30,[sp, #local_40]!
100092a64 f3 53 02 a9 stp x19,x20,[sp, #local_20]
100092a68 f5 5b 03 a9 stp x21,x22,[sp, #local_10]
100092a6c fd 03 00 91 mov x29,sp
100092a70 f3 03 00 aa mov x19,x0
100092a74 40 36 00 f0 adrp x0,___GCSTATICSS_P_CoreLib_System_Buffers_TlsO = 0000E01400127BDBh
100092a78 00 20 2b 91 add x0,x0,#0xac8
100092a7c 14 00 40 f9 ldr x20,[x0]=>___GCSTATICSS_P_CoreLib_System_Colle = 0000000000127089h
100092a80 80 06 40 f9 ldr x0,[x20, #0x8]=>DAT_00127091
100092a84 40 00 00 b5 cbnz x0,LAB_100092a8c
100092a88 2a dc 0a 94 bl _S_P_CoreLib_System_Collections_Generic_Equali undefined _S_P_CoreLib_System_Co
LAB_100092a8c XREF[1]: 100092a84(j)
100092a8c 60 02 40 f9 ldr x0,[x19]
100092a90 01 fc 60 d3 lsr x1,x0,#0x20
100092a94 00 00 01 4a eor w0,w0,w1
100092a98 35 a5 8a 52 mov w21,#0x5529
100092a9c b5 aa b4 72 movk w21,#0xa555, LSL #16
100092aa0 16 7c 15 1b mul w22,w0,w21
100092aa4 80 06 40 f9 ldr x0,[x20, #0x8]=>DAT_00127091
100092aa8 40 00 00 b5 cbnz x0,LAB_100092ab0
100092aac 21 dc 0a 94 bl _S_P_CoreLib_System_Collections_Generic_Equali undefined _S_P_CoreLib_System_Co
LAB_100092ab0 XREF[1]: 100092aa8(j)
100092ab0 60 06 40 f9 ldr x0,[x19, #0x8]
100092ab4 01 fc 60 d3 lsr x1,x0,#0x20
100092ab8 00 00 01 4a eor w0,w0,w1
100092abc 00 00 16 0b add w0,w0,w22
100092ac0 14 7c 15 1b mul w20,w0,w21
100092ac4 40 36 00 f0 adrp x0,___GCSTATICSS_P_CoreLib_System_Buffers_TlsO = 0000E01400127BDBh
100092ac8 00 c0 29 91 add x0,x0,#0xa70
100092acc 16 00 40 f9 ldr x22,[x0]=>___GCSTATICSS_P_CoreLib_System_Colle = 00000000001270E1h
100092ad0 c0 06 40 f9 ldr x0,[x22, #0x8]=>DAT_001270e9
100092ad4 40 00 00 b5 cbnz x0,LAB_100092adc
100092ad8 be d3 0a 94 bl _S_P_CoreLib_System_Collections_Generic_Equali undefined _S_P_CoreLib_System_Co
LAB_100092adc XREF[1]: 100092ad4(j)
100092adc 70 12 40 bd ldr s16,[x19, #0x10]
100092ae0 b0 1f 00 bd str s16,[x29, #local_24]
100092ae4 a0 1f 40 b9 ldr w0,[x29, #local_24]
100092ae8 01 04 00 51 sub w1,w0,#0x1
100092aec 21 78 00 12 and w1,w1,#0x7fffffff
100092af0 02 f0 af 52 mov w2,#0x7f800000
100092af4 03 1c 09 12 and w3,w0,#0x7f800000
100092af8 3f 00 02 6b cmp w1,w2
100092afc 60 a0 80 1a csel w0,w3,w0,ge
100092b00 80 02 00 0b add w0,w20,w0
100092b04 14 7c 15 1b mul w20,w0,w21
100092b08 c0 06 40 f9 ldr x0,[x22, #0x8]=>DAT_001270e9
100092b0c 40 00 00 b5 cbnz x0,LAB_100092b14
100092b10 b0 d3 0a 94 bl _S_P_CoreLib_System_Collections_Generic_Equali undefined _S_P_CoreLib_System_Co
LAB_100092b14 XREF[1]: 100092b0c(j)
100092b14 70 16 40 bd ldr s16,[x19, #0x14]
100092b18 b0 1b 00 bd str s16,[x29, #local_28]
100092b1c a0 1b 40 b9 ldr w0,[x29, #local_28]
100092b20 01 04 00 51 sub w1,w0,#0x1
100092b24 21 78 00 12 and w1,w1,#0x7fffffff
100092b28 02 f0 af 52 mov w2,#0x7f800000
100092b2c 03 1c 09 12 and w3,w0,#0x7f800000
100092b30 3f 00 02 6b cmp w1,w2
100092b34 60 a0 80 1a csel w0,w3,w0,ge
100092b38 80 02 00 0b add w0,w20,w0
100092b3c f5 5b 43 a9 ldp x21,x22,[sp, #local_10]
100092b40 f3 53 42 a9 ldp x19,x20,[sp, #local_20]
100092b44 fd 7b c4 a8 ldp x29=>local_40,x30,[sp], #0x40
100092b48 c0 03 5f d6 ret
100092b4c 00 00 00 00 align align(4)I can't claim to understand everything that's going on, especially why there's a reference to ArrayPool (Ghidra's demangling and relocs resolving?), but cctor checks do seem to be apparent and make sense.
At the same time, for JIT the following assembly is emitted:
; Assembly listing for method Report:GetHashCode():int:this
; Emitting BLENDED_CODE for generic ARM64 CPU - MacOS
; Tier-1 compilation
; optimized code
; optimized using profile data
; fp based frame
; partially interruptible
; with Dynamic PGO: edge weights are valid, and fgCalledCount is 4999
; 6 inlinees with PGO data; 10 single block inlinees; 0 inlinees without PGO data
G_M000_IG01: ;; offset=0000H
A9BE7BFD stp fp, lr, [sp, #-0x20]!
910003FD mov fp, sp
G_M000_IG02: ;; offset=0008H
F9400001 ldr x1, [x0]
D360FC22 lsr x2, x1, #32
4A020021 eor w1, w1, w2
528AA522 movz w2, #0x5529
72B4AAA2 movk w2, #0xA555 LSL #16
1B027C21 mul w1, w1, w2
F9400403 ldr x3, [x0, #0x08]
D360FC64 lsr x4, x3, #32
4A040063 eor w3, w3, w4
1B020461 madd w1, w3, w2, w1
BD401010 ldr s16, [x0, #0x10]
BD001FB0 str s16, [fp, #0x1C]
B9401FA3 ldr w3, [fp, #0x1C]
51000464 sub w4, w3, #1
12007884 and w4, w4, #0x7FFFFFFF
52AFF005 mov w5, #0x7F800000
12091C66 and w6, w3, #0x7F800000
6B05009F cmp w4, w5
1A83A0C3 csel w3, w6, w3, ge
1B020461 madd w1, w3, w2, w1
BD401410 ldr s16, [x0, #0x14]
BD001BB0 str s16, [fp, #0x18]
B9401BA0 ldr w0, [fp, #0x18]
51000402 sub w2, w0, #1
12007842 and w2, w2, #0x7FFFFFFF
12091C03 and w3, w0, #0x7F800000
6B05005F cmp w2, w5
1A80A060 csel w0, w3, w0, ge
0B000020 add w0, w1, w0
G_M000_IG03: ;; offset=007CH
A8C27BFD ldp fp, lr, [sp], #0x20
D65F03C0 ret lr
; Total bytes of code 132Regression?
No. Maybe vs JIT?
Notes
Can compiler-generated methods have special-cased handling for commonly used types in records? Does it make sense to submit an issue for this?