Skip to content

Commit b71e09a

Browse files
Add ThisptrRetbufPrecode to set of precodes handled by StubPrecode path (#112548)
This adds the ThisPtrRetBufPrecode to the set of codes handled by the StubPrecode stub pasting path. Perf changes from about 2.35 ns per iteration of a minimal loop with a ThisPtrRetBufPrecode to about 3.03 ns per iteration on my computer (Windows X64). I expect the cost to be a little less on an Arm64 machine since the old ThisPtrRetBufPrecode was a bit more expensive there. However, this removes the previous scheme where we allocate and jit custom stubs for this, so I think the simplification is worth the runtime cost. The overall change has a size increase though, as this work adds support for this type of precode to the cDAC, as well as some tests.
1 parent 79edb64 commit b71e09a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+702
-670
lines changed

docs/design/datacontracts/PrecodeStubs.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This contract provides support for examining [precode](../coreclr/botr/method-de
99
TargetPointer GetMethodDescFromStubAddress(TargetCodePointer entryPoint);
1010
```
1111

12-
## Version 1
12+
## Version 1 and 2
1313

1414
Data descriptors used:
1515
| Data Descriptor Name | Field | Meaning |
@@ -24,9 +24,12 @@ Data descriptors used:
2424
| PrecodeMachineDescriptor | PInvokeImportPrecodeType| precode sort byte for PInvoke precode stubs, if supported |
2525
| PrecodeMachineDescriptor | HasFixupPrecode | 1 if platform supports fixup precode stubs |
2626
| PrecodeMachineDescriptor | FixupPrecodeType| precode sort byte for fixup precode stubs, if supported |
27-
| StubPrecodeData | MethodDesc | pointer to the MethodDesc associated with this stub precode |
27+
| PrecodeMachineDescriptor | ThisPointerRetBufPrecodeType | precode sort byte for this pointer ret buf precodes |
28+
| StubPrecodeData | MethodDesc | pointer to the MethodDesc associated with this stub precode (Version 1 only) |
29+
| StubPrecodeData | SecretParam | pointer to the MethodDesc associated with this stub precode or a second stub data pointer for other types (Version 2 only) |
2830
| StubPrecodeData | Type | precise sort of stub precode |
2931
| FixupPrecodeData | MethodDesc | pointer to the MethodDesc associated with this fixup precode |
32+
| ThisPtrRetBufPrecodeData | MethodDesc | pointer to the MethodDesc associated with the ThisPtrRetBufPrecode (Version 2 only) |
3033

3134
arm32 note: the `CodePointerToInstrPointerMask` is used to convert IP values that may include an arm Thumb bit (for example extracted from disassembling a call instruction or from a snapshot of the registers) into an address. On other architectures applying the mask is a no-op.
3235

@@ -145,7 +148,10 @@ After the initial precode type is determined, for stub precodes a refined precod
145148
internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor)
146149
{
147150
TargetPointer stubPrecodeDataAddress = InstrPointer + precodeMachineDescriptor.StubCodePageSize;
148-
return target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.MethodDesc */ );
151+
if (ContractVersion(PrecodeStubs) == 1)
152+
return target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.MethodDesc */ );
153+
else
154+
return target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.SecretParam */ );
149155
}
150156
}
151157

@@ -170,7 +176,10 @@ After the initial precode type is determined, for stub precodes a refined precod
170176

171177
internal override TargetPointer GetMethodDesc(Target target, Data.PrecodeMachineDescriptor precodeMachineDescriptor)
172178
{
173-
throw new NotImplementedException(); // TODO(cdac)
179+
if (ContractVersion(PrecodeStubs) == 1)
180+
throw new NotImplementedException(); // TODO(cdac)
181+
else
182+
return target.ReadPointer(target.ReadPointer (stubPrecodeDataAddress + /* offset of StubPrecodeData.SecretParam */ ) + /*offset of ThisPtrRetBufPrecodeData.MethodDesc*/);
174183
}
175184
}
176185

src/coreclr/debug/runtimeinfo/contracts.jsonc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"Loader": 1,
1818
"Object": 1,
1919
"PlatformMetadata": 1,
20-
"PrecodeStubs": 1,
20+
"PrecodeStubs": 2,
2121
"ReJIT": 1,
2222
"RuntimeTypeSystem": 1,
2323
"StackWalk": 1,

src/coreclr/debug/runtimeinfo/datadescriptor.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,10 +492,17 @@ CDAC_TYPE_END(PlatformMetadata)
492492

493493
CDAC_TYPE_BEGIN(StubPrecodeData)
494494
CDAC_TYPE_INDETERMINATE(StubPrecodeData)
495-
CDAC_TYPE_FIELD(StubPrecodeData, /*pointer*/, MethodDesc, offsetof(StubPrecodeData, SecretParam))
495+
CDAC_TYPE_FIELD(StubPrecodeData, /*pointer*/, SecretParam, offsetof(StubPrecodeData, SecretParam))
496496
CDAC_TYPE_FIELD(StubPrecodeData, /*uint8*/, Type, offsetof(StubPrecodeData, Type))
497497
CDAC_TYPE_END(StubPrecodeData)
498498

499+
#ifdef HAS_THISPTR_RETBUF_PRECODE
500+
CDAC_TYPE_BEGIN(ThisPtrRetBufPrecodeData)
501+
CDAC_TYPE_INDETERMINATE(ThisPtrRetBufPrecodeData)
502+
CDAC_TYPE_FIELD(ThisPtrRetBufPrecodeData, /*pointer*/, MethodDesc, offsetof(ThisPtrRetBufPrecodeData, MethodDesc))
503+
CDAC_TYPE_END(ThisPtrRetBufPrecodeData)
504+
#endif
505+
499506
CDAC_TYPE_BEGIN(FixupPrecodeData)
500507
CDAC_TYPE_INDETERMINATE(FixupPrecodeData)
501508
CDAC_TYPE_FIELD(FixupPrecodeData, /*pointer*/, MethodDesc, offsetof(FixupPrecodeData, MethodDesc))

src/coreclr/vm/amd64/AsmHelpers.asm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,4 +497,14 @@ NESTED_ENTRY InterpreterStub, _TEXT
497497
NESTED_END InterpreterStub, _TEXT
498498
endif ; FEATURE_INTERPRETER
499499

500+
; rcx -This pointer
501+
; rdx -ReturnBuffer
502+
LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT
503+
mov METHODDESC_REGISTER, [METHODDESC_REGISTER + ThisPtrRetBufPrecodeData__Target]
504+
mov r11, rcx
505+
mov rcx, rdx
506+
mov rdx, r11
507+
jmp METHODDESC_REGISTER
508+
LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT
509+
500510
end

src/coreclr/vm/amd64/asmconstants.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#define DynamicHelperFrameFlags_ObjectArg 1
3535
#define DynamicHelperFrameFlags_ObjectArg2 2
3636

37+
#define ThisPtrRetBufPrecodeData__Target 0x00
38+
ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target));
39+
3740
#define ASMCONSTANT_OFFSETOF_ASSERT(struct, member) \
3841
ASMCONSTANTS_C_ASSERT(OFFSETOF__##struct##__##member == offsetof(struct, member));
3942

src/coreclr/vm/amd64/asmhelpers.S

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,13 @@ NESTED_ENTRY InterpreterStub, _TEXT, NoHandler
352352

353353
NESTED_END InterpreterStub, _TEXT
354354
#endif // FEATURE_INTERPRETER
355+
356+
//rdi -This pointer
357+
//rsi -ReturnBuffer
358+
LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT
359+
mov METHODDESC_REGISTER, [METHODDESC_REGISTER + ThisPtrRetBufPrecodeData__Target]
360+
mov r11, rsi
361+
mov rsi, rdi
362+
mov rdi, r11
363+
jmp METHODDESC_REGISTER
364+
LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT

src/coreclr/vm/arm/asmconstants.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ ASMCONSTANTS_C_ASSERT(FRAMETYPE_InlinedCallFrame == (int)FrameIdentifier::Inline
3636
#define DynamicHelperFrameFlags_ObjectArg 1
3737
#define DynamicHelperFrameFlags_ObjectArg2 2
3838

39+
#define ThisPtrRetBufPrecodeData__Target 0x00
40+
ASMCONSTANTS_C_ASSERT(ThisPtrRetBufPrecodeData__Target == offsetof(ThisPtrRetBufPrecodeData, Target));
41+
3942
#define REDIRECTSTUB_SP_OFFSET_CONTEXT 0
4043

4144

src/coreclr/vm/arm/asmhelpers.S

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,3 +977,15 @@ LOCAL_LABEL(JIT_PollGCRarePath):
977977
ldr r2, [r2]
978978
EPILOG_BRANCH_REG r2
979979
LEAF_END JIT_PollGC, _TEXT
980+
981+
982+
//x0 -This pointer
983+
//x1 -ReturnBuffer
984+
LEAF_ENTRY ThisPtrRetBufPrecodeWorker, _TEXT
985+
ldr r12, [r12, #ThisPtrRetBufPrecodeData__Target]
986+
// Use XOR swap technique to set avoid the need to spill to the stack
987+
eor r0, r0, r1
988+
eor r1, r0, r1
989+
eor r0, r0, r1
990+
EPILOG_BRANCH_REG r12
991+
LEAF_END ThisPtrRetBufPrecodeWorker, _TEXT

src/coreclr/vm/arm/cgencpu.h

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -962,63 +962,6 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool
962962
// Create alias for optimized implementations of helpers provided on this platform
963963
//
964964

965-
//------------------------------------------------------------------------
966-
//
967-
// Precode definitions
968-
//
969-
//------------------------------------------------------------------------
970-
//
971-
// Note: If you introduce new precode implementation below, then please
972-
// update PrecodeStubManager::CheckIsStub_Internal to account for it.
973-
974-
// Precode to shuffle this and retbuf for closed delegates over static methods with return buffer
975-
struct ThisPtrRetBufPrecode {
976-
977-
static const int Type = 0x01;
978-
979-
// mov r12, r0
980-
// mov r0, r1
981-
// mov r1, r12
982-
// ldr pc, [pc, #0] ; =m_pTarget
983-
// dcd pTarget
984-
// dcd pMethodDesc
985-
WORD m_rgCode[6];
986-
TADDR m_pTarget;
987-
TADDR m_pMethodDesc;
988-
989-
void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator);
990-
991-
TADDR GetMethodDesc()
992-
{
993-
LIMITED_METHOD_DAC_CONTRACT;
994-
995-
return m_pMethodDesc;
996-
}
997-
998-
PCODE GetTarget()
999-
{
1000-
LIMITED_METHOD_DAC_CONTRACT;
1001-
return m_pTarget;
1002-
}
1003-
1004-
#ifndef DACCESS_COMPILE
1005-
BOOL SetTargetInterlocked(TADDR target, TADDR expected)
1006-
{
1007-
CONTRACTL
1008-
{
1009-
THROWS;
1010-
GC_TRIGGERS;
1011-
}
1012-
CONTRACTL_END;
1013-
1014-
ExecutableWriterHolder<ThisPtrRetBufPrecode> precodeWriterHolder(this, sizeof(ThisPtrRetBufPrecode));
1015-
return InterlockedCompareExchange((LONG*)&precodeWriterHolder.GetRW()->m_pTarget, (LONG)target, (LONG)expected) == (LONG)expected;
1016-
}
1017-
#endif // !DACCESS_COMPILE
1018-
};
1019-
typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode;
1020-
1021-
1022965
//**********************************************************************
1023966
// Miscellaneous
1024967
//**********************************************************************

src/coreclr/vm/arm/stubs.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -733,26 +733,6 @@ void HelperMethodFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool update
733733

734734
#ifndef DACCESS_COMPILE
735735

736-
void ThisPtrRetBufPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator)
737-
{
738-
WRAPPER_NO_CONTRACT;
739-
740-
int n = 0;
741-
742-
m_rgCode[n++] = 0x4684; // mov r12, r0
743-
m_rgCode[n++] = 0x4608; // mov r0, r1
744-
m_rgCode[n++] = 0xea4f; // mov r1, r12
745-
m_rgCode[n++] = 0x010c;
746-
m_rgCode[n++] = 0xf8df; // ldr pc, [pc, #0]
747-
m_rgCode[n++] = 0xf000;
748-
749-
_ASSERTE(n == ARRAY_SIZE(m_rgCode));
750-
751-
m_pTarget = GetPreStubEntryPoint();
752-
m_pMethodDesc = (TADDR)pMD;
753-
}
754-
755-
756736
/*
757737
Rough pseudo-code of interface dispatching:
758738

0 commit comments

Comments
 (0)