Skip to content

Commit 8ed9046

Browse files
author
Aman Khalid
committed
Update fake-splitting implementation on ARM64
To facilitate generating unwind info, fake-splitting now places the read-only data section after the cold section. This allows the hot/cold code sections to be truly contiguous.
1 parent d208b3a commit 8ed9046

File tree

4 files changed

+49
-50
lines changed

4 files changed

+49
-50
lines changed

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7646,7 +7646,7 @@ class Compiler
76467646

76477647
// ICorJitInfo wrappers
76487648

7649-
void eeAllocMem(AllocMemArgs* args);
7649+
void eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSectionAlignment);
76507650

76517651
void eeReserveUnwindInfo(bool isFunclet, bool isColdCode, ULONG unwindSize);
76527652

src/coreclr/jit/ee_il_dll.cpp

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,34 +1122,64 @@ void Compiler::eeDispLineInfos()
11221122
* (e.g., host AMD64, target ARM64), then VM will get confused anyway.
11231123
*/
11241124

1125-
void Compiler::eeAllocMem(AllocMemArgs* args)
1125+
void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSectionAlignment)
11261126
{
11271127
#ifdef DEBUG
1128-
const UNATIVE_OFFSET hotSizeRequest = args->hotCodeSize;
1129-
const UNATIVE_OFFSET coldSizeRequest = args->coldCodeSize;
11301128

1131-
// Fake splitting implementation: place hot/cold code in contiguous section
1132-
if (JitConfig.JitFakeProcedureSplitting() && (coldSizeRequest > 0))
1129+
// Fake splitting implementation: place hot/cold code in contiguous section.
1130+
UNATIVE_OFFSET coldCodeOffset = 0;
1131+
if (JitConfig.JitFakeProcedureSplitting() && (args->coldCodeSize > 0))
11331132
{
1134-
args->hotCodeSize = hotSizeRequest + coldSizeRequest;
1133+
coldCodeOffset = args->hotCodeSize;
1134+
assert(coldCodeOffset > 0);
1135+
args->hotCodeSize += args->coldCodeSize;
11351136
args->coldCodeSize = 0;
11361137
}
1137-
#endif
1138+
1139+
#endif // DEBUG
1140+
1141+
#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
1142+
1143+
// For arm64/LoongArch64, we want to allocate JIT data always adjacent to code similar to what native compiler does.
1144+
// This way allows us to use a single `ldr` to access such data like float constant/jmp table.
1145+
// For LoongArch64 using `pcaddi + ld` to access such data.
1146+
1147+
UNATIVE_OFFSET roDataAlignmentDelta = 0;
1148+
if (args->roDataSize > 0)
1149+
{
1150+
roDataAlignmentDelta = AlignmentPad(args->hotCodeSize, roDataSectionAlignment);
1151+
}
1152+
1153+
const UNATIVE_OFFSET roDataOffset = args->hotCodeSize + roDataAlignmentDelta;
1154+
args->hotCodeSize = roDataOffset + args->roDataSize;
1155+
args->roDataSize = 0;
1156+
1157+
#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
11381158

11391159
info.compCompHnd->allocMem(args);
11401160

11411161
#ifdef DEBUG
1142-
if (JitConfig.JitFakeProcedureSplitting() && (coldSizeRequest > 0))
1143-
{
1144-
// Fix up hot/cold code pointers
1145-
args->coldCodeBlock = ((BYTE*)args->hotCodeBlock) + hotSizeRequest;
1146-
args->coldCodeBlockRW = ((BYTE*)args->hotCodeBlockRW) + hotSizeRequest;
11471162

1148-
// Reset args' hot/cold code sizes in case caller reads them later
1149-
args->hotCodeSize = hotSizeRequest;
1150-
args->coldCodeSize = coldSizeRequest;
1163+
if (JitConfig.JitFakeProcedureSplitting() && (coldCodeOffset > 0))
1164+
{
1165+
// Fix up cold code pointers. Cold section is adjacent to hot section.
1166+
assert(args->coldCodeBlock == nullptr);
1167+
assert(args->coldCodeBlockRW == nullptr);
1168+
args->coldCodeBlock = ((BYTE*)args->hotCodeBlock) + coldCodeOffset;
1169+
args->coldCodeBlockRW = ((BYTE*)args->hotCodeBlockRW) + coldCodeOffset;
11511170
}
1152-
#endif
1171+
1172+
#endif // DEBUG
1173+
1174+
#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
1175+
1176+
// Fix up data section pointers.
1177+
assert(args->roDataBlock == nullptr);
1178+
assert(args->roDataBlockRW == nullptr);
1179+
args->roDataBlock = ((BYTE*)args->hotCodeBlock) + roDataOffset;
1180+
args->roDataBlockRW = ((BYTE*)args->hotCodeBlockRW) + roDataOffset;
1181+
1182+
#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
11531183
}
11541184

11551185
void Compiler::eeReserveUnwindInfo(bool isFunclet, bool isColdCode, ULONG unwindSize)

src/coreclr/jit/emit.cpp

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6304,38 +6304,13 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
63046304
AllocMemArgs args;
63056305
memset(&args, 0, sizeof(args));
63066306

6307-
#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
6308-
// For arm64/LoongArch64, we want to allocate JIT data always adjacent to code similar to what native compiler does.
6309-
// This way allows us to use a single `ldr` to access such data like float constant/jmp table.
6310-
6311-
const UNATIVE_OFFSET roDataAlignmentDelta =
6312-
(UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, emitConsDsc.alignment) - emitTotalHotCodeSize;
6313-
6314-
args.hotCodeSize = emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs;
6315-
args.coldCodeSize = emitTotalColdCodeSize;
6316-
args.roDataSize = 0;
6317-
args.xcptnsCount = xcptnsCount;
6318-
args.flag = allocMemFlag;
6319-
6320-
emitComp->eeAllocMem(&args);
6321-
6322-
codeBlock = (BYTE*)args.hotCodeBlock;
6323-
codeBlockRW = (BYTE*)args.hotCodeBlockRW;
6324-
coldCodeBlock = (BYTE*)args.coldCodeBlock;
6325-
coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW;
6326-
6327-
consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta;
6328-
consBlockRW = codeBlockRW + emitTotalHotCodeSize + roDataAlignmentDelta;
6329-
6330-
#else
6331-
63326307
args.hotCodeSize = emitTotalHotCodeSize;
63336308
args.coldCodeSize = emitTotalColdCodeSize;
63346309
args.roDataSize = emitConsDsc.dsdOffs;
63356310
args.xcptnsCount = xcptnsCount;
63366311
args.flag = allocMemFlag;
63376312

6338-
emitComp->eeAllocMem(&args);
6313+
emitComp->eeAllocMem(&args, emitConsDsc.alignment);
63396314

63406315
codeBlock = (BYTE*)args.hotCodeBlock;
63416316
codeBlockRW = (BYTE*)args.hotCodeBlockRW;
@@ -6344,8 +6319,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
63446319
consBlock = (BYTE*)args.roDataBlock;
63456320
consBlockRW = (BYTE*)args.roDataBlockRW;
63466321

6347-
#endif
6348-
63496322
#ifdef DEBUG
63506323
if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0)
63516324
{

src/coreclr/jit/emitarm64.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8437,8 +8437,7 @@ void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
84378437
{
84388438
case INS_bl_local:
84398439
idjShort = true;
8440-
fmt = IF_BI_0A;
8441-
break;
8440+
FALLTHROUGH;
84428441
case INS_b:
84438442
// Unconditional jump is a single form.
84448443
// Assume is long in case we cross hot/cold sections.
@@ -9841,9 +9840,6 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
98419840
// Special case: emit add + ld1 instructions for loading 16-byte data into vector register.
98429841
if (isVectorRegister(dstReg) && (opSize == EA_16BYTE))
98439842
{
9844-
// Low 4 bits should be 0 -- 16-byte JIT data should be aligned on 16 bytes.
9845-
assert((imm12 & 15) == 0);
9846-
98479843
const emitAttr elemSize = EA_1BYTE;
98489844
const insOpts opt = optMakeArrangement(opSize, elemSize);
98499845

0 commit comments

Comments
 (0)