Skip to content

Commit d7ab48f

Browse files
committed
Fix a couple bugs; improve documentation
1. Improve the frame shape pictures, especially for arm64 funclet frames. Include the MonitorAcquired element and OSR pad. 2. Fix bug for `SP_to_PSP_slot_delta` for funclet frame type 4 for OSR: don't include osrPad. 3. Fix bug with funclet frame type 5 for `SP_to_FPLR_save_delta` using wrong aligned func size; would be incorrect if one and two SP adjustment full frame aligned sizes are different (e.g., if two SP adjustment required two alignment slots and one SP adjustment thus required none).
1 parent 24d12fc commit d7ab48f

2 files changed

Lines changed: 56 additions & 29 deletions

File tree

src/coreclr/jit/codegenarm64.cpp

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,10 +1078,14 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
10781078
* |-----------------------|
10791079
* | incoming arguments |
10801080
* +=======================+ <---- Caller's SP
1081+
* | OSR padding | // If required
1082+
* |-----------------------|
10811083
* | Varargs regs space | // Only for varargs main functions; 64 bytes
10821084
* |-----------------------|
10831085
* |Callee saved registers | // multiple of 8 bytes
10841086
* |-----------------------|
1087+
* | MonitorAcquired | // 8 bytes; for synchronized methods
1088+
* |-----------------------|
10851089
* | PSP slot | // 8 bytes (omitted in NativeAOT ABI)
10861090
* |-----------------------|
10871091
* ~ alignment padding ~ // To make the whole frame 16 byte aligned.
@@ -1105,10 +1109,14 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
11051109
* |-----------------------|
11061110
* | incoming arguments |
11071111
* +=======================+ <---- Caller's SP
1112+
* | OSR padding | // If required
1113+
* |-----------------------|
11081114
* | Varargs regs space | // Only for varargs main functions; 64 bytes
11091115
* |-----------------------|
11101116
* |Callee saved registers | // multiple of 8 bytes
11111117
* |-----------------------|
1118+
* | MonitorAcquired | // 8 bytes; for synchronized methods
1119+
* |-----------------------|
11121120
* | PSP slot | // 8 bytes (omitted in NativeAOT ABI)
11131121
* |-----------------------|
11141122
* ~ alignment padding ~ // To make the whole frame 16 byte aligned.
@@ -1135,20 +1143,24 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
11351143
* |-----------------------|
11361144
* | incoming arguments |
11371145
* +=======================+ <---- Caller's SP
1146+
* | OSR padding | // If required
1147+
* |-----------------------|
11381148
* | Varargs regs space | // Only for varargs main functions; 64 bytes
11391149
* |-----------------------|
11401150
* |Callee saved registers | // multiple of 8 bytes
11411151
* |-----------------------|
1152+
* | MonitorAcquired | // 8 bytes; for synchronized methods
1153+
* |-----------------------|
11421154
* | PSP slot | // 8 bytes (omitted in NativeAOT ABI)
11431155
* |-----------------------|
11441156
* ~ alignment padding ~ // To make the first SP subtraction 16 byte aligned
11451157
* |-----------------------|
1146-
* | Saved FP, LR | // 16 bytes
1158+
* | Saved FP, LR | // 16 bytes <-- SP after first adjustment (points at saved FP)
11471159
* |-----------------------|
11481160
* ~ alignment padding ~ // To make the whole frame 16 byte aligned (specifically, to 16-byte align the outgoing argument space).
11491161
* |-----------------------|
11501162
* | Outgoing arg space | // multiple of 8 bytes
1151-
* |-----------------------| <---- Ambient SP
1163+
* |-----------------------| <---- Ambient SP (SP after second adjustment)
11521164
* | | |
11531165
* ~ | Stack grows ~
11541166
* | | downward |
@@ -1163,7 +1175,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
11631175
* 8 float callee-saved registers v8-v15
11641176
* 8 saved integer argument registers x0-x7, if varargs function
11651177
* 1 PSP slot
1166-
* 1 alignment slot
1178+
* 1 alignment slot or monitor acquired slot
11671179
* == 30 slots * 8 bytes = 240 bytes.
11681180
*
11691181
* The outgoing argument size, however, can be very large, if we call a function that takes a large number of
@@ -1199,6 +1211,8 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
11991211
* |-----------------------|
12001212
* | incoming arguments |
12011213
* +=======================+ <---- Caller's SP
1214+
* | OSR padding | // If required
1215+
* |-----------------------|
12021216
* | Varargs regs space | // Only for varargs main functions; 64 bytes
12031217
* |-----------------------|
12041218
* | Saved LR | // 8 bytes
@@ -1207,6 +1221,8 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
12071221
* |-----------------------|
12081222
* |Callee saved registers | // multiple of 8 bytes
12091223
* |-----------------------|
1224+
* | MonitorAcquired | // 8 bytes; for synchronized methods
1225+
* |-----------------------|
12101226
* | PSP slot | // 8 bytes (omitted in NativeAOT ABI)
12111227
* |-----------------------|
12121228
* ~ alignment padding ~ // To make the whole frame 16 byte aligned.
@@ -1236,6 +1252,8 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
12361252
* |-----------------------|
12371253
* | incoming arguments |
12381254
* +=======================+ <---- Caller's SP
1255+
* | OSR padding | // If required
1256+
* |-----------------------|
12391257
* | Varargs regs space | // Only for varargs main functions; 64 bytes
12401258
* |-----------------------|
12411259
* | Saved LR | // 8 bytes
@@ -1244,14 +1262,16 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
12441262
* |-----------------------|
12451263
* |Callee saved registers | // multiple of 8 bytes
12461264
* |-----------------------|
1265+
* | MonitorAcquired | // 8 bytes; for synchronized methods
1266+
* |-----------------------|
12471267
* | PSP slot | // 8 bytes (omitted in NativeAOT ABI)
12481268
* |-----------------------|
1249-
* ~ alignment padding ~ // To make the first SP subtraction 16 byte aligned
1269+
* ~ alignment padding ~ // To make the first SP subtraction 16 byte aligned <-- SP after first adjustment (points at alignment padding or PSP slot)
12501270
* |-----------------------|
12511271
* ~ alignment padding ~ // To make the whole frame 16 byte aligned (specifically, to 16-byte align the outgoing argument space).
12521272
* |-----------------------|
12531273
* | Outgoing arg space | // multiple of 8 bytes
1254-
* |-----------------------| <---- Ambient SP
1274+
* |-----------------------| <---- Ambient SP (SP after second adjustment)
12551275
* | | |
12561276
* ~ | Stack grows ~
12571277
* | | downward |
@@ -1311,6 +1331,8 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in
13111331
* ldp fp,lr,[sp],#framesz
13121332
* ret lr
13131333
*
1334+
* See CodeGen::genPushCalleeSavedRegisters() for a description of the main function frame layout.
1335+
* See Compiler::lvaAssignVirtualFrameOffsetsToLocals() for calculation of main frame local variable offsets.
13141336
*/
13151337
// clang-format on
13161338

@@ -1504,6 +1526,8 @@ void CodeGen::genFuncletProlog(BasicBlock* block)
15041526
/*****************************************************************************
15051527
*
15061528
* Generates code for an EH funclet epilog.
1529+
*
1530+
* See the description of frame shapes at genFuncletProlog().
15071531
*/
15081532

15091533
void CodeGen::genFuncletEpilog()
@@ -1711,43 +1735,50 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
17111735
assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0);
17121736
unsigned const outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN);
17131737

1714-
unsigned const maxFuncletFrameSizeAligned = osrPad + saveRegsPlusPSPSizeAligned + outgoingArgSpaceAligned;
1715-
assert((maxFuncletFrameSizeAligned % STACK_ALIGN) == 0);
1738+
// If do two SP adjustments, each one must be aligned. This represents the largest possible stack size, if two
1739+
// separate alignment slots are required.
1740+
unsigned const twoSpAdjustmentFuncletFrameSizeAligned =
1741+
osrPad + saveRegsPlusPSPSizeAligned + outgoingArgSpaceAligned;
1742+
assert((twoSpAdjustmentFuncletFrameSizeAligned % STACK_ALIGN) == 0);
17161743

17171744
int SP_to_FPLR_save_delta;
17181745
int SP_to_PSP_slot_delta;
17191746
int CallerSP_to_PSP_slot_delta;
17201747

1721-
unsigned const funcletFrameSize = osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize;
1722-
unsigned const funcletFrameSizeAligned = roundUp(funcletFrameSize, STACK_ALIGN);
1723-
assert(funcletFrameSizeAligned <= maxFuncletFrameSizeAligned);
1724-
1725-
unsigned const funcletFrameAlignmentPad = funcletFrameSizeAligned - funcletFrameSize;
1726-
assert((funcletFrameAlignmentPad == 0) || (funcletFrameAlignmentPad == REGSIZE_BYTES));
1727-
17281748
// Are we stressing frame type 5? Don't do it unless we have non-zero outgoing arg space.
17291749
const bool useFrameType5 =
17301750
genSaveFpLrWithAllCalleeSavedRegisters && genForceFuncletFrameType5 && (compiler->lvaOutgoingArgSpaceSize > 0);
17311751

1732-
if ((maxFuncletFrameSizeAligned <= 512) && !useFrameType5)
1752+
if ((twoSpAdjustmentFuncletFrameSizeAligned <= 512) && !useFrameType5)
17331753
{
1754+
unsigned const oneSpAdjustmentFuncletFrameSize =
1755+
osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize;
1756+
unsigned const oneSpAdjustmentFuncletFrameSizeAligned = roundUp(oneSpAdjustmentFuncletFrameSize, STACK_ALIGN);
1757+
assert(oneSpAdjustmentFuncletFrameSizeAligned <= twoSpAdjustmentFuncletFrameSizeAligned);
1758+
1759+
unsigned const oneSpAdjustmentFuncletFrameSizeAlignmentPad =
1760+
oneSpAdjustmentFuncletFrameSizeAligned - oneSpAdjustmentFuncletFrameSize;
1761+
assert((oneSpAdjustmentFuncletFrameSizeAlignmentPad == 0) ||
1762+
(oneSpAdjustmentFuncletFrameSizeAlignmentPad == REGSIZE_BYTES));
1763+
17341764
if (genSaveFpLrWithAllCalleeSavedRegisters)
17351765
{
1736-
SP_to_FPLR_save_delta = funcletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES);
1766+
SP_to_FPLR_save_delta = oneSpAdjustmentFuncletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES);
17371767
if (compiler->info.compIsVarArgs)
17381768
{
17391769
SP_to_FPLR_save_delta -= MAX_REG_ARG * REGSIZE_BYTES;
17401770
}
17411771

1742-
SP_to_PSP_slot_delta = compiler->lvaOutgoingArgSpaceSize + funcletFrameAlignmentPad + osrPad;
1772+
SP_to_PSP_slot_delta = compiler->lvaOutgoingArgSpaceSize + oneSpAdjustmentFuncletFrameSizeAlignmentPad;
17431773
CallerSP_to_PSP_slot_delta = -(int)(osrPad + saveRegsPlusPSPSize);
17441774

17451775
genFuncletInfo.fiFrameType = 4;
17461776
}
17471777
else
17481778
{
17491779
SP_to_FPLR_save_delta = compiler->lvaOutgoingArgSpaceSize;
1750-
SP_to_PSP_slot_delta = SP_to_FPLR_save_delta + 2 /* FP, LR */ * REGSIZE_BYTES + funcletFrameAlignmentPad;
1780+
SP_to_PSP_slot_delta =
1781+
SP_to_FPLR_save_delta + 2 /* FP, LR */ * REGSIZE_BYTES + oneSpAdjustmentFuncletFrameSizeAlignmentPad;
17511782
CallerSP_to_PSP_slot_delta = -(int)(osrPad + saveRegsPlusPSPSize - 2 /* FP, LR */ * REGSIZE_BYTES);
17521783

17531784
if (compiler->lvaOutgoingArgSpaceSize == 0)
@@ -1760,10 +1791,10 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
17601791
}
17611792
}
17621793

1763-
genFuncletInfo.fiSpDelta1 = -(int)funcletFrameSizeAligned;
1794+
genFuncletInfo.fiSpDelta1 = -(int)oneSpAdjustmentFuncletFrameSizeAligned;
17641795
genFuncletInfo.fiSpDelta2 = 0;
17651796

1766-
assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)funcletFrameSizeAligned);
1797+
assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)oneSpAdjustmentFuncletFrameSizeAligned);
17671798
}
17681799
else
17691800
{
@@ -1772,17 +1803,13 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
17721803

17731804
if (genSaveFpLrWithAllCalleeSavedRegisters)
17741805
{
1775-
SP_to_FPLR_save_delta = funcletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES);
1806+
SP_to_FPLR_save_delta = twoSpAdjustmentFuncletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES);
17761807
if (compiler->info.compIsVarArgs)
17771808
{
17781809
SP_to_FPLR_save_delta -= MAX_REG_ARG * REGSIZE_BYTES;
17791810
}
17801811

1781-
unsigned const outgoingArgSpaceAlignmentPad = outgoingArgSpaceAligned - compiler->lvaOutgoingArgSpaceSize;
1782-
assert((outgoingArgSpaceAlignmentPad == 0) || (outgoingArgSpaceAlignmentPad == REGSIZE_BYTES));
1783-
1784-
SP_to_PSP_slot_delta =
1785-
compiler->lvaOutgoingArgSpaceSize + outgoingArgSpaceAlignmentPad + saveRegsPlusPSPAlignmentPad;
1812+
SP_to_PSP_slot_delta = outgoingArgSpaceAligned + saveRegsPlusPSPAlignmentPad;
17861813
CallerSP_to_PSP_slot_delta = -(int)(osrPad + saveRegsPlusPSPSize);
17871814

17881815
genFuncletInfo.fiFrameType = 5;
@@ -1800,7 +1827,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
18001827
genFuncletInfo.fiSpDelta1 = -(int)(osrPad + saveRegsPlusPSPSizeAligned);
18011828
genFuncletInfo.fiSpDelta2 = -(int)outgoingArgSpaceAligned;
18021829

1803-
assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)maxFuncletFrameSizeAligned);
1830+
assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)twoSpAdjustmentFuncletFrameSizeAligned);
18041831
}
18051832

18061833
/* Now save it for future use */

src/coreclr/jit/codegenarmarch.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4651,7 +4651,7 @@ void CodeGen::genPushCalleeSavedRegisters()
46514651
// |-----------------------|
46524652
// |Callee saved registers | // not including FP/LR; multiple of 8 bytes
46534653
// |-----------------------|
4654-
// | MonitorAcquired |
4654+
// | MonitorAcquired | // 8 bytes; for synchronized methods
46554655
// |-----------------------|
46564656
// | PSP slot | // 8 bytes (omitted in NativeAOT ABI)
46574657
// |-----------------------|
@@ -4684,7 +4684,7 @@ void CodeGen::genPushCalleeSavedRegisters()
46844684
// |-----------------------|
46854685
// |Callee saved registers | // not including FP/LR; multiple of 8 bytes
46864686
// |-----------------------|
4687-
// | MonitorAcquired |
4687+
// | MonitorAcquired | // 8 bytes; for synchronized methods
46884688
// |-----------------------|
46894689
// | PSP slot | // 8 bytes (omitted in NativeAOT ABI)
46904690
// |-----------------------|

0 commit comments

Comments
 (0)