You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This adds support for EnC on arm64. A couple of notes on the
implementation compared to x64:
- On x64 we get the fixed stack size from unwind info. However, for the
frames we set up on arm64 for EnC it is not possible to extract the
frame size from there because their prologs generally look like
stp fp, lr, [sp,#-16]!
mov fp, sp
sub sp, sp, dotnet#144
with unwind codes like the following:
set_fp; mov fp, sp
save_fplr_x #1 (0x01); tp fp, lr, [sp, #-16]!
As can be seen, it is not possible to get the fixed stack size from
unwind info in this case. Instead we pass it through the GC info that
already has a section for EnC data.
- On arm64 the JIT is required to place the PSPSym at the same offset
from caller-SP for both the main function and for funclets. Due to
this we try to allocate the PSPSym as early as possible in the main
function and we must take some care in funclets. However, this
conflicts with the EnC frame header that the JIT uses to place values
that must be preserved on EnC transitions. This is currently
callee-saved registers and the MonitorAcquired boolean.
Before this change we were allocating PSPSym above (before) the
monitor acquired boolean, but we now have to allocate MonitorAcquired
first, particularly because the size of the preserved header cannot
change on EnC transitions, while the PSPSym can disappear or appear.
This changes frame allocation slightly for synchronized functions.
Copy file name to clipboardExpand all lines: docs/design/coreclr/botr/clr-abi.md
+13-8Lines changed: 13 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -653,41 +653,46 @@ Edit and Continue (EnC) is a special flavor of un-optimized code. The debugger h
653
653
654
654
In the current design, the JIT does not have access to the previous versions of the method and so it has to assume the worst case. EnC is designed for simplicity, not for performance of the generated code.
655
655
656
-
EnC is currently enabled on x86and x64 only, but the same principles would apply if it is ever enabled on other platforms.
656
+
EnC is currently enabled on x86, x64 and ARM64 only, but the same principles would apply if it is ever enabled on other platforms.
657
657
658
658
The following sections describe the various Edit and Continue code conventions that must be followed.
659
659
660
660
## EnC flag in GCInfo
661
661
662
-
The JIT records the fact that it has followed conventions for EnC code in GC Info. On x64, this flag is implied by recording the size of the stack frame region preserved between EnC edits (`GcInfoEncoder::SetSizeOfEditAndContinuePreservedArea`). For normal methods on JIT64, the size of this region is 2 slots (saved `RBP` and return address). On RyuJIT/AMD64, the size of this region is increased to include `RSI` and `RDI`, so that `rep stos` can be used for block initialization and block moves.
662
+
The JIT records the fact that it has followed conventions for EnC code in GC Info. On x64/ARM64, this flag is implied by recording the size of the stack frame region preserved between EnC edits (`GcInfoEncoder::SetSizeOfEditAndContinuePreservedArea`). For x64 the size of this region is increased to include `RSI` and `RDI`, so that `rep stos` can be used for block initialization and block moves. ARM64 saves only the FP and LR registers when EnC is enabled and does not use other callee saved registers.
663
+
664
+
To successfully perform EnC transitions the runtime needs to know the size of the stack frames it is transitioning between. For x64 code the size can be extracted from unwind codes. This is not possible for arm64 code as the frames are set up in such a way that the unwind codes do not allow to retrieve this value. Therefore, on ARM64 the GC info contains also the size of the fixed stack frame to be used for EnC purposes.
663
665
664
666
## Allocating local variables backward
665
667
666
668
This is required to preserve addresses of the existing locals when an EnC edit appends new ones. In other words, the first local must be allocated at the highest stack address. Special care has to be taken to deal with alignment. The total size of the method frame can either grow (more locals added) or shrink (fewer temps needed) after the edit. The VM zeros out newly added locals.
667
669
668
670
## Fixed set of callee-saved registers
669
671
670
-
This eliminates need to deal with the different sets in the VM, and makes preservation of local addresses easier. On x64, we choose to always save `RBP` only. There are plenty of volatile registers and so lack of non-volatile registers does not impact quality of non-optimized code.
672
+
This eliminates need to deal with the different sets in the VM, and makes preservation of local addresses easier. There are plenty of volatile registers and so lack of non-volatile registers does not heavily impact quality of non-optimized code.
673
+
x64 currently saves RBP, RSI and RDI while ARM64 saves just FP and LR.
671
674
672
675
## EnC is supported for methods with EH
673
676
674
677
However, EnC remap is not supported inside funclets. The stack layout of funclets does not matter for EnC.
675
678
676
-
## Initial RSP == RBP == PSPSym
679
+
## Considerations with regards to PSPSym
677
680
678
-
This invariant allows VM to compute new value of `RBP` and PSPSym after the edit without any additional information. Location of PSPSym is found via GC info.
681
+
As explained previously in this document, on x64 we have Initial RSP == PSPSym. For EnC methods, as we disallow remappings after localloc (see below), we furthermore have RBP == PSPSym.
682
+
For ARM64 we have Caller SP == PSPSym and the FP points to the previously saved FP/LR pair. For EnC the JIT always sets up the stack frame so that the FP/LR pair is at Caller SP - 16 and does not save any additional callee saves.
683
+
These invariants allow the VM to compute new value of the frame pointer and PSPSym after the edit without any additional information. Note that the frame pointer and PSPSym do not change values or location on ARM64. However, EH may be added to a function in which case a new PSPSym needs to be materialized, even on ARM64. Location of PSPSym is found via GC info.
679
684
680
685
## Localloc
681
686
682
-
Localloc is allowed in EnC code, but remap is disallowed after the method has executed a localloc instruction. VM uses the invariant above (`RSP == RBP`) to detect whether localloc was executed by the method.
687
+
Localloc is allowed in EnC code, but remap is disallowed after the method has executed a localloc instruction. VM uses the invariants above (`RSP == RBP` on x64, `FP + 16 == SP + stack size` on ARM64) to detect whether localloc was executed by the method.
683
688
684
689
## Security object
685
690
686
-
This does not require any special handling by the JIT on x64. (Different from x86). The security object is copied over by the VM during remap if necessary. Location of security object is found via GC info.
691
+
This does not require any special handling by the JIT on x64/arm64. (Different from x86). The security object is copied over by the VM during remap if necessary. Location of security object is found via GC info.
687
692
688
693
## Synchronized methods
689
694
690
-
The extra state created by the JIT for synchronized methods (original `this` and lock taken flag) must be preserved during remap. The JIT stores this state in the preserved region, and increases the size of the preserved region reported in GC info accordingly.
695
+
The extra state created by the JIT for synchronized methods (lock taken flag) must be preserved during remap. The JIT stores this state in the preserved region, and increases the size of the preserved region reported in GC info accordingly.
0 commit comments