Skip to content

Allow fasttail calls for engregesterable structs #5

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

Closed
Closed
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
21 changes: 14 additions & 7 deletions src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8186,13 +8186,20 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
bool compPublishStubParam : 1; // EAX captured in prolog will be available through an instrinsic
bool compRetBuffDefStack : 1; // The ret buff argument definitely points into the stack.

var_types compRetType; // Return type of the method as declared in IL
var_types compRetNativeType; // Normalized return type as per target arch ABI
unsigned compILargsCount; // Number of arguments (incl. implicit but not hidden)
unsigned compArgsCount; // Number of arguments (incl. implicit and hidden)
unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present);
int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE)
unsigned compThisArg; // position of implicit this pointer param (not to be confused with lvaArg0Var)
var_types compRetType; // Return type of the method as declared in IL
var_types compRetNativeType; // Normalized return type as per target arch ABI
unsigned compILargsCount; // Number of arguments (incl. implicit but not hidden)
unsigned compArgsCount; // Number of arguments (incl. implicit and hidden)

#ifdef FEATURE_MULTIREG_ARGS
unsigned compArgRegCount; // Number of caller integer args
unsigned compFloatArgRegCount; // Number of caller floating point args
unsigned compStackSize; // Caller stack size
#endif // FEATURE_MULTIREG_ARGS

unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present);
int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE)
unsigned compThisArg; // position of implicit this pointer param (not to be confused with lvaArg0Var)
unsigned compILlocalsCount; // Number of vars : args + locals (incl. implicit but not hidden)
unsigned compLocalsCount; // Number of vars : args + locals (incl. implicit and hidden)
unsigned compMaxStack;
Expand Down
78 changes: 70 additions & 8 deletions src/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,19 @@ void Compiler::lvaInitTypeRef()
/* Set compArgsCount and compLocalsCount */

info.compArgsCount = info.compMethodInfo->args.numArgs;
unsigned argRegCount = 0;

auto incrementArgCount = [this, &argRegCount]()
{
++info.compArgsCount;
++argRegCount;
};

// Is there a 'this' pointer

if (!info.compIsStatic)
{
info.compArgsCount++;
incrementArgCount();
}
else
{
Expand Down Expand Up @@ -167,7 +174,7 @@ void Compiler::lvaInitTypeRef()

if (hasRetBuffArg)
{
info.compArgsCount++;
incrementArgCount();
}
else
{
Expand All @@ -179,14 +186,14 @@ void Compiler::lvaInitTypeRef()

if (info.compIsVarArgs)
{
info.compArgsCount++;
incrementArgCount();
}

// Is there an extra parameter used to pass instantiation info to
// shared generic methods and shared generic struct instance methods?
if (info.compMethodInfo->args.callConv & CORINFO_CALLCONV_PARAMTYPE)
{
info.compArgsCount++;
incrementArgCount();
}
else
{
Expand Down Expand Up @@ -233,15 +240,54 @@ void Compiler::lvaInitTypeRef()
InitVarDscInfo varDscInfo;
varDscInfo.Init(lvaTable, hasRetBuffArg);

// Maintain a pointer to the start of the arguments.
LclVarDsc* varDscTrailingPointer = varDscInfo.varDsc;
lvaInitArgs(&varDscInfo);

//-------------------------------------------------------------------------
// Calculate the argument register usage.
//
// This will later be used for fastTailCall determination
//-------------------------------------------------------------------------

unsigned floatingRegCount = 0;
unsigned stackArgCount = 0;
unsigned stackSize = 0;

auto incrementRegCount = [&floatingRegCount, &argRegCount](LclVarDsc* varDsc)
{
varDsc->IsFloatRegType() ? ++floatingRegCount : ++argRegCount;
};

for (unsigned argNum = 0; argNum < info.compMethodInfo->args.numArgs; argNum++, varDscTrailingPointer++)
{
if (varDscTrailingPointer->lvRegNum != REG_STK)
{
incrementRegCount(varDscTrailingPointer);

#ifdef FEATURE_MULTIREG_ARGS
if (varDscTrailingPointer->lvOtherArgReg != REG_NA)
{
incrementRegCount(varDscTrailingPointer);
}
#endif // FEATURE_MULTIREG_ARGS
}
else
{
stackSize += varDscTrailingPointer->lvSize();
}
}

//-------------------------------------------------------------------------
// Finally the local variables
//-------------------------------------------------------------------------

unsigned varNum = varDscInfo.varNum;
LclVarDsc* varDsc = varDscInfo.varDsc;
CORINFO_ARG_LIST_HANDLE localsSig = info.compMethodInfo->locals.args;
unsigned varNum = varDscInfo.varNum;
LclVarDsc* varDsc = varDscInfo.varDsc;
CORINFO_ARG_LIST_HANDLE localsSig = info.compMethodInfo->locals.args;

// Maintain a pointer to the start of the locals.
varDscTrailingPointer = varDsc;

for (unsigned i = 0; i < info.compMethodInfo->locals.numArgs;
i++, varNum++, varDsc++, localsSig = info.compCompHnd->getArgNext(localsSig))
Expand All @@ -255,13 +301,25 @@ void Compiler::lvaInitTypeRef()
varDsc->lvPinned = ((corInfoType & CORINFO_TYPE_MOD_PINNED) != 0);
varDsc->lvOnFrame = true; // The final home for this local variable might be our local stack frame

CORINFO_CLASS_HANDLE clsHnd = info.compCompHnd->getArgClass(&info.compMethodInfo->locals, localsSig);
stackSize += roundUp(compGetTypeSize(strip(corInfoType), clsHnd), TARGET_POINTER_SIZE);

if (strip(corInfoType) == CORINFO_TYPE_CLASS)
{
CORINFO_CLASS_HANDLE clsHnd = info.compCompHnd->getArgClass(&info.compMethodInfo->locals, localsSig);
lvaSetClass(varNum, clsHnd);
}
}

//-------------------------------------------------------------------------
// Save the register usage information and stack size.
//-------------------------------------------------------------------------

stackSize += stackArgCount * REGSIZE_BYTES;

info.compArgRegCount = argRegCount;
info.compFloatArgRegCount = floatingRegCount;
info.compStackSize = stackSize;

if ( // If there already exist unsafe buffers, don't mark more structs as unsafe
// as that will cause them to be placed along with the real unsafe buffers,
// unnecessarily exposing them to overruns. This can affect GS tests which
Expand Down Expand Up @@ -1253,6 +1311,10 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc,
#ifdef DEBUG
varDsc->lvStkOffs = BAD_STK_OFFS;
#endif

#ifdef FEATURE_MULTIREG_ARGS
varDsc->lvOtherArgReg = REG_NA;
#endif // FEATURE_MULTIREG_ARGS
}

/*****************************************************************************
Expand Down
1 change: 0 additions & 1 deletion src/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,6 @@ void Lowering::LowerFastTailCall(GenTreeCall* call)
fgArgTabEntryPtr argTabEntry = comp->gtArgEntryByNode(call, putArgStkNode);
assert(argTabEntry);
unsigned callerArgNum = argTabEntry->argNum - calleeNonStandardArgCount;
noway_assert(callerArgNum < comp->info.compArgsCount);

unsigned callerArgLclNum = callerArgNum;
LclVarDsc* callerArgDsc = comp->lvaTable + callerArgLclNum;
Expand Down
Loading