Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Simplify internal GC tracking structures #113071

Merged
merged 1 commit into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 9 additions & 17 deletions src/coreclr/jit/emit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9983,7 +9983,6 @@ void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callIn

unsigned argStkCnt;
S_UINT16 argRecCnt(0); // arg count for ESP, ptr-arg count for EBP
unsigned gcrefRegs, byrefRegs;

#ifdef JIT32_GCENCODER
// For the general encoder, we always need to record calls, so we make this call
Expand Down Expand Up @@ -10025,26 +10024,19 @@ void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callIn
return;
#endif

// Do we have any interesting (i.e., callee-saved) registers live here?
// Do we have any interesting registers live here?

gcrefRegs = byrefRegs = 0;
unsigned gcrefRegs = emitThisGCrefRegs.GetIntRegSet() >> REG_INT_FIRST;
unsigned byrefRegs = emitThisByrefRegs.GetIntRegSet() >> REG_INT_FIRST;

// We make a bitmask whose bits correspond to callee-saved register indices (in the sequence
// of callee-saved registers only).
for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALL_GC_REGS; calleeSavedRegIdx++)
{
regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx];
if (emitThisGCrefRegs & calleeSavedRbm)
{
gcrefRegs |= (1 << calleeSavedRegIdx);
}
if (emitThisByrefRegs & calleeSavedRbm)
{
byrefRegs |= (1 << calleeSavedRegIdx);
}
}
assert(regMaskTP::FromIntRegSet(SingleTypeRegSet(gcrefRegs << REG_INT_FIRST)) == emitThisGCrefRegs);
assert(regMaskTP::FromIntRegSet(SingleTypeRegSet(byrefRegs << REG_INT_FIRST)) == emitThisByrefRegs);

#ifdef JIT32_GCENCODER
// x86 does not report GC refs/byrefs in return registers at call sites
gcrefRegs &= ~(1u << (REG_INTRET - REG_INT_FIRST));
byrefRegs &= ~(1u << (REG_INTRET - REG_INT_FIRST));

// For the general encoder, we always have to record calls, so we don't take this early return. /* Are there any
// args to pop at this call site?

Expand Down
30 changes: 21 additions & 9 deletions src/coreclr/jit/gcencode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3199,9 +3199,24 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un

callArgCnt = genRegPtrTemp->rpdPtrArg;

unsigned gcrefRegMask = genRegPtrTemp->rpdCallGCrefRegs;
unsigned gcrefRegMask = 0;

byrefRegMask = genRegPtrTemp->rpdCallByrefRegs;
byrefRegMask = 0;

// The order here is fixed: it must agree with the order assumed in eetwain.
// NB: x86 GC decoder does not report return registers at call sites.
static const regNumber calleeSaveOrder[] = {REG_EDI, REG_ESI, REG_EBX, REG_EBP};
for (unsigned i = 0; i < ArrLen(calleeSaveOrder); i++)
{
if ((genRegPtrTemp->rpdCallGCrefRegs & (1 << (calleeSaveOrder[i] - REG_INT_FIRST))) != 0)
{
gcrefRegMask |= 1u << i;
}
if ((genRegPtrTemp->rpdCallByrefRegs & (1 << (calleeSaveOrder[i] - REG_INT_FIRST))) != 0)
{
byrefRegMask |= 1u << i;
}
}

assert((gcrefRegMask & byrefRegMask) == 0);

Expand Down Expand Up @@ -4465,8 +4480,8 @@ void GCInfo::gcMakeRegPtrTable(
assert(call->u1.cdArgMask == 0 && call->cdArgCnt == 0);

// Other than that, we just have to deal with the regmasks.
regMaskSmall gcrefRegMask = call->cdGCrefRegs & RBM_CALL_GC_REGS.GetIntRegSet();
regMaskSmall byrefRegMask = call->cdByrefRegs & RBM_CALL_GC_REGS.GetIntRegSet();
regMaskSmall gcrefRegMask = call->cdGCrefRegs;
regMaskSmall byrefRegMask = call->cdByrefRegs;

assert((gcrefRegMask & byrefRegMask) == 0);

Expand Down Expand Up @@ -4552,11 +4567,8 @@ void GCInfo::gcMakeRegPtrTable(
{
// This is a true call site.

regMaskSmall gcrefRegMask =
genRegMaskFromCalleeSavedMask(genRegPtrTemp->rpdCallGCrefRegs).GetIntRegSet();

regMaskSmall byrefRegMask =
genRegMaskFromCalleeSavedMask(genRegPtrTemp->rpdCallByrefRegs).GetIntRegSet();
regMaskSmall gcrefRegMask = regMaskSmall(genRegPtrTemp->rpdCallGCrefRegs << REG_INT_FIRST);
regMaskSmall byrefRegMask = regMaskSmall(genRegPtrTemp->rpdCallByrefRegs << REG_INT_FIRST);

assert((gcrefRegMask & byrefRegMask) == 0);

Expand Down
15 changes: 9 additions & 6 deletions src/coreclr/jit/jitgcinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,13 @@ class GCInfo
regMaskSmall rpdDel; // regptr bitset being removed
} rpdCompiler;

unsigned short rpdPtrArg; // arg offset or popped arg count
struct
{
// Registers after call containing GC/byref (index 0 = REG_INT_FIRST)
unsigned int rpdCallGCrefRegs;
unsigned int rpdCallByrefRegs;
unsigned short rpdPtrArg; // arg offset or popped arg count
};
};

#ifndef JIT32_GCENCODER
Expand All @@ -182,11 +188,8 @@ class GCInfo
return (GCtype)rpdGCtype;
}

unsigned short rpdIsThis : 1; // is it the 'this' pointer
unsigned short rpdCall : 1; // is this a true call site?
unsigned short : 1; // Padding bit, so next two start on a byte boundary
unsigned short rpdCallGCrefRegs : CNT_CALL_GC_REGS; // Callee-saved and return registers containing GC pointers.
unsigned short rpdCallByrefRegs : CNT_CALL_GC_REGS; // Callee-saved and return registers containing byrefs.
unsigned short rpdIsThis : 1; // is it the 'this' pointer
unsigned short rpdCall : 1; // is this a true call site?

#ifndef JIT32_GCENCODER
bool rpdIsCallInstr()
Expand Down
21 changes: 0 additions & 21 deletions src/coreclr/jit/regset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -944,27 +944,6 @@ regNumber genRegArgNext(regNumber argReg)
}
}

/*****************************************************************************
*
* The following table determines the order in which callee registers
* are encoded in GC information at call sites.
*/

const regMaskTP raRbmCalleeSaveOrder[] = {RBM_CALL_GC_REGS_ORDER};

regMaskTP genRegMaskFromCalleeSavedMask(unsigned short calleeSaveMask)
{
regMaskTP res = 0;
for (int i = 0; i < CNT_CALL_GC_REGS; i++)
{
if ((calleeSaveMask & (1 << i)) != 0)
{
res |= raRbmCalleeSaveOrder[i];
}
}
return res;
}

/*****************************************************************************
*
* Initializes the spill code. Should be called once per function compiled.
Expand Down
15 changes: 5 additions & 10 deletions src/coreclr/jit/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,11 @@ struct regMaskTP
#endif
}

static regMaskTP FromIntRegSet(SingleTypeRegSet intRegs)
{
return regMaskTP(intRegs);
}

void operator|=(const regMaskTP& second)
{
low |= second.getLow();
Expand Down Expand Up @@ -1066,16 +1071,6 @@ inline SingleTypeRegSet getSingleTypeRegMask(regNumber reg, var_types regType)
return regMask;
}

/*****************************************************************************
*
* These arrays list the callee-saved register numbers (and bitmaps, respectively) for
* the current architecture.
*/
extern const regMaskTP raRbmCalleeSaveOrder[CNT_CALL_GC_REGS];

// This method takes a "compact" bitset of the callee-saved registers, and "expands" it to a full register mask.
regMaskTP genRegMaskFromCalleeSavedMask(unsigned short);

/*****************************************************************************
*
* Assumes that "reg" is of the given "type". Return the next unused reg number after "reg"
Expand Down
8 changes: 0 additions & 8 deletions src/coreclr/jit/targetamd64.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,24 +300,19 @@
#ifdef UNIX_AMD64_ABI
#define CNT_CALLEE_SAVED (5 + REG_ETW_FRAMED_EBP_COUNT)
#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED)
#define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED + 2)

#define CNT_CALLEE_TRASH_INT_INIT (9)
#define CNT_CALLEE_TRASH_HIGHINT (8)

#define CNT_CALLEE_SAVED_FLOAT (0)
#define CNT_CALLEE_TRASH_FLOAT_INIT (16)
#define CNT_CALLEE_TRASH_HIGHFLOAT (16)
/* NOTE: Sync with variable name defined in compiler.h */
#define RBM_CALL_GC_REGS_ORDER RBM_EBX,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15,RBM_INTRET,RBM_INTRET_1
#define RBM_CALL_GC_REGS (RBM_EBX|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_INTRET|RBM_INTRET_1)

// For SysV we have more volatile registers so we do not save any callee saves for EnC.
#define RBM_ENC_CALLEE_SAVED 0
#else // !UNIX_AMD64_ABI
#define CNT_CALLEE_SAVED (7 + REG_ETW_FRAMED_EBP_COUNT)
#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED)
#define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED + 1)

#define CNT_CALLEE_TRASH_INT_INIT (7)
#define CNT_CALLEE_TRASH_HIGHINT (8)
Expand All @@ -326,9 +321,6 @@
#define CNT_CALLEE_SAVED_FLOAT (10)
#define CNT_CALLEE_TRASH_FLOAT_INIT (6)
#define CNT_CALLEE_TRASH_HIGHFLOAT (16)
/* NOTE: Sync with variable name defined in compiler.h */
#define RBM_CALL_GC_REGS_ORDER RBM_EBX,RBM_ESI,RBM_EDI,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15,RBM_INTRET
#define RBM_CALL_GC_REGS (RBM_EBX|RBM_ESI|RBM_EDI|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_INTRET)

// Callee-preserved registers we always save and allow use of for EnC code, since there are quite few volatile registers.
#define RBM_ENC_CALLEE_SAVED (RBM_RSI | RBM_RDI)
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/jit/targetarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,9 @@
#define RBM_LOW_REGS (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7)
#define RBM_HIGH_REGS (RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_SP|RBM_LR|RBM_PC)

#define RBM_CALL_GC_REGS_ORDER RBM_R4,RBM_R5,RBM_R6,RBM_R7,RBM_R8,RBM_R9,RBM_R10,RBM_R11,RBM_INTRET
#define RBM_CALL_GC_REGS (RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_INTRET)

#define CNT_CALLEE_SAVED (8)
#define CNT_CALLEE_TRASH (6)
#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1)
#define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+1)

#define CNT_CALLEE_SAVED_FLOAT (16)
#define CNT_CALLEE_TRASH_FLOAT (16)
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/jit/targetarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,9 @@
REG_V12, REG_V13, REG_V14, REG_V15, \
REG_V3, REG_V2, REG_V1, REG_V0

#define RBM_CALL_GC_REGS_ORDER RBM_R19,RBM_R20,RBM_R21,RBM_R22,RBM_R23,RBM_R24,RBM_R25,RBM_R26,RBM_R27,RBM_R28,RBM_INTRET,RBM_INTRET_1
#define RBM_CALL_GC_REGS (RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28|RBM_INTRET|RBM_INTRET_1)

#define CNT_CALLEE_SAVED (11)
#define CNT_CALLEE_TRASH (17)
#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1)
#define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+2)

#define CNT_CALLEE_SAVED_FLOAT (8)
#define CNT_CALLEE_TRASH_FLOAT (24)
Expand Down
7 changes: 0 additions & 7 deletions src/coreclr/jit/targetx86.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,9 @@
#define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX
#define MAX_VAR_ORDER_SIZE 6

// The order here is fixed: it must agree with an order assumed in eetwain...
// NB: x86 GC decoder does not report return registers at call sites.
#define RBM_CALL_GC_REGS_ORDER RBM_EDI,RBM_ESI,RBM_EBX,RBM_EBP
#define RBM_CALL_GC_REGS (RBM_EDI|RBM_ESI|RBM_EBX|RBM_EBP)

#define CNT_CALLEE_SAVED (4)
#define CNT_CALLEE_TRASH (3)
#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1)
// NB: x86 GC decoder does not report return registers at call sites.
#define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED)

#define CNT_CALLEE_SAVED_FLOAT (0)
#define CNT_CALLEE_TRASH_FLOAT (6)
Expand Down
Loading