Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Use ClassLayout in LclVarDsc
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedn committed Apr 24, 2019
1 parent 4043b0f commit bc48bce
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 233 deletions.
14 changes: 6 additions & 8 deletions src/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,8 +726,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
// the xor ensures that only one of the two is setup, not both
assert((varNode != nullptr) ^ (addrNode != nullptr));

BYTE gcPtrArray[MAX_ARG_REG_COUNT] = {}; // TYPE_GC_NONE = 0
const BYTE* gcPtrs = gcPtrArray;
const BYTE* gcPtrs = nullptr;

unsigned gcPtrCount; // The count of GC pointers in the struct
unsigned structSize;
Expand All @@ -753,9 +752,8 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
// as that is how much stack is allocated for this LclVar
isHfa = varDsc->lvIsHfa();
#ifdef _TARGET_ARM64_
gcPtrCount = varDsc->lvStructGcCount;
for (unsigned i = 0; i < gcPtrCount; ++i)
gcPtrArray[i] = varDsc->lvGcLayout[i];
gcPtrCount = varDsc->GetLayout()->GetGCPtrCount();
gcPtrs = varDsc->GetLayout()->GetGCPtrs();
#endif // _TARGET_ARM_
}
else // we must have a GT_OBJ
Expand Down Expand Up @@ -2736,7 +2734,7 @@ void CodeGen::genJmpMethod(GenTree* jmp)
// Must be <= 16 bytes or else it wouldn't be passed in registers, except for HFA,
// which can be bigger (and is handled above).
noway_assert(EA_SIZE_IN_BYTES(varDsc->lvSize()) <= 16);
loadType = compiler->getJitGCType(varDsc->lvGcLayout[0]);
loadType = varDsc->GetLayout()->GetGCPtrType(0);
}
else
{
Expand All @@ -2757,7 +2755,7 @@ void CodeGen::genJmpMethod(GenTree* jmp)
// Restore the second register.
argRegNext = genRegArgNext(argReg);

loadType = compiler->getJitGCType(varDsc->lvGcLayout[1]);
loadType = varDsc->GetLayout()->GetGCPtrType(1);
loadSize = emitActualTypeSize(loadType);
getEmitter()->emitIns_R_S(ins_Load(loadType), loadSize, argRegNext, varNum, TARGET_POINTER_SIZE);

Expand Down Expand Up @@ -2850,7 +2848,7 @@ void CodeGen::genJmpMethod(GenTree* jmp)
for (unsigned ofs = 0; ofs < maxSize; ofs += REGSIZE_BYTES)
{
unsigned idx = ofs / REGSIZE_BYTES;
loadType = compiler->getJitGCType(varDsc->lvGcLayout[idx]);
loadType = varDsc->GetLayout()->GetGCPtrType(idx);

if (varDsc->lvRegNum != argReg)
{
Expand Down
24 changes: 14 additions & 10 deletions src/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4512,8 +4512,7 @@ void CodeGen::genCheckUseBlockInit()
continue;
}

if (compiler->info.compInitMem || varTypeIsGC(varDsc->TypeGet()) || (varDsc->lvStructGcCount > 0) ||
varDsc->lvMustInit)
if (compiler->info.compInitMem || varDsc->HasGCPtr() || varDsc->lvMustInit)
{
if (varDsc->lvTracked)
{
Expand Down Expand Up @@ -4559,7 +4558,7 @@ void CodeGen::genCheckUseBlockInit()
CLANG_FORMAT_COMMENT_ANCHOR;

if ((!varDsc->lvTracked || (varDsc->lvType == TYP_STRUCT)) && varDsc->lvOnFrame &&
(!varDsc->lvIsTemp || varTypeIsGC(varDsc->TypeGet()) || (varDsc->lvStructGcCount > 0)))
(!varDsc->lvIsTemp || varDsc->HasGCPtr()))
{

varDsc->lvMustInit = true;
Expand All @@ -4576,7 +4575,7 @@ void CodeGen::genCheckUseBlockInit()

/* Ignore if not a pointer variable or value class with a GC field */

if (!compiler->lvaTypeIsGC(varNum))
if (!varDsc->HasGCPtr())
{
continue;
}
Expand All @@ -4597,13 +4596,18 @@ void CodeGen::genCheckUseBlockInit()

/* Is this a 'must-init' stack pointer local? */

if (varDsc->lvMustInit && varDsc->lvOnFrame)
if (varDsc->lvMustInit && varDsc->lvOnFrame && !counted)
{
if (!counted)
if (varDsc->TypeGet() == TYP_STRUCT)
{
initStkLclCnt += varDsc->lvStructGcCount;
counted = true;
initStkLclCnt += varDsc->GetLayout()->GetGCPtrCount();
}
else
{
assert(varTypeIsGC(varDsc->TypeGet()));
initStkLclCnt += 1;
}
counted = true;
}

if ((compiler->lvaLclSize(varNum) > (3 * TARGET_POINTER_SIZE)) && (largeGcStructs <= 4))
Expand Down Expand Up @@ -6338,7 +6342,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg,
{
// We only initialize the GC variables in the TYP_STRUCT
const unsigned slots = (unsigned)compiler->lvaLclSize(varNum) / REGSIZE_BYTES;
const BYTE* gcPtrs = compiler->lvaGetGcLayout(varNum);
const BYTE* gcPtrs = varDsc->GetLayout()->GetGCPtrs();

for (unsigned i = 0; i < slots; i++)
{
Expand Down Expand Up @@ -7761,7 +7765,7 @@ void CodeGen::genFnProlog()
/* We need to know the offset range of tracked stack GC refs */
/* We assume that the GC reference can be anywhere in the TYP_STRUCT */

if (compiler->lvaTypeIsGC(varNum) && varDsc->lvTrackedNonStruct() && varDsc->lvOnFrame)
if (varDsc->HasGCPtr() && varDsc->lvTrackedNonStruct() && varDsc->lvOnFrame)
{
// For fields of PROMOTION_TYPE_DEPENDENT type of promotion, they should have been
// taken care of by the parent struct.
Expand Down
20 changes: 2 additions & 18 deletions src/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4931,28 +4931,12 @@ bool Compiler::compQuirkForPPP()
// This fixes the PPP backward compat issue
varDscExposedStruct->lvExactSize += 32;

// Update the GC info to indicate that the padding area does
// not contain any GC pointers.
//
// The struct is now 64 bytes.
//
// We're on x64 so this should be 8 pointer slots.
assert((varDscExposedStruct->lvExactSize / TARGET_POINTER_SIZE) == 8);

BYTE* oldGCPtrs = varDscExposedStruct->lvGcLayout;
BYTE* newGCPtrs = getAllocator(CMK_LvaTable).allocate<BYTE>(8);

for (int i = 0; i < 4; i++)
{
newGCPtrs[i] = oldGCPtrs[i];
}

for (int i = 4; i < 8; i++)
{
newGCPtrs[i] = TYPE_GC_NONE;
}

varDscExposedStruct->lvGcLayout = newGCPtrs;
varDscExposedStruct->SetLayout(
varDscExposedStruct->GetLayout()->GetPPPQuirkLayout(getAllocator(CMK_ClassLayout)));

return true;
}
Expand Down
41 changes: 28 additions & 13 deletions src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,12 +566,10 @@ class LclVarDsc
unsigned char lvIsRegArg : 1; // is this a register argument?
unsigned char lvFramePointerBased : 1; // 0 = off of REG_SPBASE (e.g., ESP), 1 = off of REG_FPBASE (e.g., EBP)

unsigned char lvStructGcCount : 3; // if struct, how many GC pointer (stop counting at 7). The only use of values >1
// is to help determine whether to use block init in the prolog.
unsigned char lvOnFrame : 1; // (part of) the variable lives on the frame
unsigned char lvRegister : 1; // assigned to live in a register? For RyuJIT backend, this is only set if the
// variable is in the same register for the entire function.
unsigned char lvTracked : 1; // is this a tracked variable?
unsigned char lvOnFrame : 1; // (part of) the variable lives on the frame
unsigned char lvRegister : 1; // assigned to live in a register? For RyuJIT backend, this is only set if the
// variable is in the same register for the entire function.
unsigned char lvTracked : 1; // is this a tracked variable?
bool lvTrackedNonStruct()
{
return lvTracked && lvType != TYP_STRUCT;
Expand Down Expand Up @@ -1038,8 +1036,10 @@ class LclVarDsc

CORINFO_FIELD_HANDLE lvFieldHnd; // field handle for promoted struct fields

BYTE* lvGcLayout; // GC layout info for structs
private:
ClassLayout* m_layout; // layout info for structs

public:
#if ASSERTION_PROP
BlockSet lvRefBlks; // Set of blocks that contain refs
GenTreeStmt* lvDefStmt; // Pointer to the statement with the single definition
Expand Down Expand Up @@ -1096,6 +1096,26 @@ class LclVarDsc

var_types lvaArgType();

// Returns true if this variable contains GC pointers (including being a GC pointer itself).
bool HasGCPtr()
{
return varTypeIsGC(lvType) || ((lvType == TYP_STRUCT) && m_layout->HasGCPtr());
}

// Returns the layout of a struct variable.
ClassLayout* GetLayout()
{
assert(varTypeIsStruct(lvType));
return m_layout;
}

// Sets the layout of a struct variable.
void SetLayout(ClassLayout* layout)
{
assert(varTypeIsStruct(lvType));
m_layout = layout;
}

SsaDefArray<LclSsaVarDsc> lvPerSsaData;

// Returns the address of the per-Ssa data for the given ssaNum (which is required
Expand Down Expand Up @@ -3509,8 +3529,6 @@ class Compiler
}
#endif // defined(FEATURE_SIMD)

BYTE* lvaGetGcLayout(unsigned varNum);
bool lvaTypeIsGC(unsigned varNum);
unsigned lvaGSSecurityCookie; // LclVar number
bool lvaTempsHaveLargerOffsetThanVars();

Expand Down Expand Up @@ -3852,10 +3870,7 @@ class Compiler

GenTree* impGetStructAddr(GenTree* structVal, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel, bool willDeref);

var_types impNormStructType(CORINFO_CLASS_HANDLE structHnd,
BYTE* gcLayout = nullptr,
unsigned* numGCVars = nullptr,
var_types* simdBaseType = nullptr);
var_types impNormStructType(CORINFO_CLASS_HANDLE structHnd, var_types* simdBaseType = nullptr);

GenTree* impNormStructVal(GenTree* structVal,
CORINFO_CLASS_HANDLE structHnd,
Expand Down
20 changes: 2 additions & 18 deletions src/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1853,22 +1853,6 @@ inline VARSET_VALRET_TP Compiler::lvaStmtLclMask(GenTreeStmt* stmt)
return lclMask;
}

/*****************************************************************************
* Returns true if the lvType is a TYP_REF or a TYP_BYREF.
* When the lvType is a TYP_STRUCT it searches the GC layout
* of the struct and returns true iff it contains a GC ref.
*/

inline bool Compiler::lvaTypeIsGC(unsigned varNum)
{
if (lvaTable[varNum].TypeGet() == TYP_STRUCT)
{
assert(lvaTable[varNum].lvGcLayout != nullptr); // bits are intialized
return (lvaTable[varNum].lvStructGcCount != 0);
}
return (varTypeIsGC(lvaTable[varNum].TypeGet()));
}

/*****************************************************************************
Is this a synchronized instance method? If so, we will need to report "this"
in the GC information, so that the EE can release the object lock
Expand Down Expand Up @@ -4127,8 +4111,8 @@ inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename)

bool Compiler::fgStructTempNeedsExplicitZeroInit(LclVarDsc* varDsc, BasicBlock* block)
{
bool containsGCPtr = (varDsc->lvStructGcCount > 0);
return (!info.compInitMem || ((block->bbFlags & BBF_BACKWARD_JUMP) != 0) || (!containsGCPtr && varDsc->lvIsTemp));
return !info.compInitMem || ((block->bbFlags & BBF_BACKWARD_JUMP) != 0) ||
(!varDsc->HasGCPtr() && varDsc->lvIsTemp);
}

/*****************************************************************************/
Expand Down
12 changes: 6 additions & 6 deletions src/jit/gcencode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2319,10 +2319,10 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un
}

// A struct will have gcSlots only if it is at least TARGET_POINTER_SIZE.
if (varDsc->lvType == TYP_STRUCT && varDsc->lvOnFrame && (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
if ((varDsc->TypeGet() == TYP_STRUCT) && varDsc->lvOnFrame && (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
{
unsigned slots = compiler->lvaLclSize(varNum) / TARGET_POINTER_SIZE;
BYTE* gcPtrs = compiler->lvaGetGcLayout(varNum);
unsigned slots = varDsc->GetLayout()->GetSlotCount();
const BYTE* gcPtrs = varDsc->GetLayout()->GetGCPtrs();

// walk each member of the array
for (unsigned i = 0; i < slots; i++)
Expand Down Expand Up @@ -4274,10 +4274,10 @@ void GCInfo::gcMakeRegPtrTable(

// If this is a TYP_STRUCT, handle its GC pointers.
// Note that the enregisterable struct types cannot have GC pointers in them.
if ((varDsc->lvType == TYP_STRUCT) && varDsc->lvOnFrame && (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
if ((varDsc->TypeGet() == TYP_STRUCT) && varDsc->lvOnFrame && (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
{
unsigned slots = compiler->lvaLclSize(varNum) / TARGET_POINTER_SIZE;
BYTE* gcPtrs = compiler->lvaGetGcLayout(varNum);
unsigned slots = varDsc->GetLayout()->GetSlotCount();
const BYTE* gcPtrs = varDsc->GetLayout()->GetGCPtrs();

// walk each member of the array
for (unsigned i = 0; i < slots; i++)
Expand Down
14 changes: 2 additions & 12 deletions src/jit/gcinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,19 +477,9 @@ void GCInfo::gcCountForHeader(UNALIGNED unsigned int* untrackedCount, UNALIGNED

count++;
}
else if (varDsc->lvType == TYP_STRUCT && varDsc->lvOnFrame && (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
else if ((varDsc->TypeGet() == TYP_STRUCT) && varDsc->lvOnFrame && (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
{
unsigned slots = compiler->lvaLclSize(varNum) / TARGET_POINTER_SIZE;
BYTE* gcPtrs = compiler->lvaGetGcLayout(varNum);

// walk each member of the array
for (unsigned i = 0; i < slots; i++)
{
if (gcPtrs[i] != TYPE_GC_NONE)
{ // count only gc slots
count++;
}
}
count += varDsc->GetLayout()->GetGCPtrCount();
}
}

Expand Down
6 changes: 1 addition & 5 deletions src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14423,12 +14423,8 @@ GenTree* Compiler::gtNewTempAssign(
if (dstTyp == TYP_UNDEF)
{
varDsc->lvType = dstTyp = genActualType(valTyp);
if (varTypeIsGC(dstTyp))
{
varDsc->lvStructGcCount = 1;
}
#if FEATURE_SIMD
else if (varTypeIsSIMD(dstTyp))
if (varTypeIsSIMD(dstTyp))
{
varDsc->lvSIMDType = 1;
}
Expand Down
7 changes: 5 additions & 2 deletions src/jit/gschecks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,11 @@ void Compiler::gsParamsToShadows()
lvaTable[shadowVar].lvLclFieldExpr = varDsc->lvLclFieldExpr;
lvaTable[shadowVar].lvLiveAcrossUCall = varDsc->lvLiveAcrossUCall;
#endif
lvaTable[shadowVar].lvVerTypeInfo = varDsc->lvVerTypeInfo;
lvaTable[shadowVar].lvGcLayout = varDsc->lvGcLayout;
lvaTable[shadowVar].lvVerTypeInfo = varDsc->lvVerTypeInfo;
if (varTypeIsStruct(type))
{
lvaTable[shadowVar].SetLayout(varDsc->GetLayout());
}
lvaTable[shadowVar].lvIsUnsafeBuffer = varDsc->lvIsUnsafeBuffer;
lvaTable[shadowVar].lvIsPtr = varDsc->lvIsPtr;

Expand Down
Loading

0 comments on commit bc48bce

Please sign in to comment.