JIT Escape Analysis: cyclic reference assignments force heap allocation; cannot eliminate escapes in simple mutual-linking case
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
JIT Escape Analysis: cyclic reference assignments force heap allocation; cannot eliminate escapes in simple mutual-linking case
### Reproduction Steps
```
TestEscapeLogic.TestEscape2();
public class A { public int Field1; public object Data; }
public class B { public int Field2; public object Data; }
public static class TestEscapeLogic
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static int TestEscape2()
{
var a = new A();
var b = new B();
a.Data = b;
b.Data = a;
return a.Field1 + b.Field2;
}
}
```
Build
```
"DOTNET_JitDisasm": "*TestEscape*",
"DOTNET_TieredCompilation": "0",
"DOTNET_ReadyToRun": "0"
dotnet run -c Release --launch-profile JitDisasm --framework net10.0
; Assembly listing for method TestEscapeLogic:TestEscape3():int (FullOpts)
; Emitting BLENDED_CODE for generic ARM64 on Apple
; FullOpts code
; optimized code
; fp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 6 single block inlinees; 0 inlinees without PGO data
G_M000_IG01: ;; offset=0x0000
stp fp, lr, [sp, #-0x20]!
stp x19, x20, [sp, #0x10]
mov fp, sp
G_M000_IG02: ;; offset=0x000C
movz x19, #0x4CC8
movk x19, #0x744 LSL #16
movk x19, #1 LSL #32
mov x0, x19
bl CORINFO_HELP_NEWSFAST
mov x20, x0
sub x0, x19, #208
bl CORINFO_HELP_NEWSFAST
add x14, x20, #8
mov x15, x0
bl CORINFO_HELP_ASSIGN_REF
add x14, x0, #8
mov x15, x20
bl CORINFO_HELP_ASSIGN_REF
ldr w1, [x20, #0x10]
ldr w0, [x0, #0x10]
add w0, w1, w0
G_M000_IG03: ;; offset=0x0050
ldp x19, x20, [sp, #0x10]
ldp fp, lr, [sp], #0x20
ret lr
; Total bytes of code 92
```
### Expected behavior
JIT should prove that a and b do not escape the method and:
either eliminate both allocations entirely (scalar replacement), or
stack allocate them (object stack allocation), since the cycle is local and unobservable.
```
G_M000_IG01: ;; offset=0x0000
stp fp, lr, [sp, #-0x10]!
mov fp, sp
G_M000_IG02: ;; offset=0x0008
mov w0, wzr
G_M000_IG03: ;; offset=0x000C
ldp fp, lr, [sp], #0x10
ret lr
; Total bytes of code 20
```
### Actual behavior
Both objects are treated as escaping / remain heap allocated (allocations are not removed)
### Regression?
_No response_
### Known Workarounds
_No response_
### Configuration
_No response_
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.